package com.smart.translator.ble;

import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import com.smart.translator.util.AdpcmDecoder;
import com.smart.translator.util.AudioResampler;
import com.smart.translator.util.AsrWsClient;
import com.smart.translator.util.DoubaoTTSManager;
import com.smart.translator.util.AdpcmEncoder;
import com.smart.translator.util.WavUtil;
import com.smart.translator.util.VadDetector;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.UUID;
import android.media.MediaPlayer;
import android.media.AudioTrack;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.content.Context;
import android.content.Intent;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import com.smart.translator.util.AliyunAsrClient;
import android.content.ComponentName;
import com.smart.translator.ble.BleManager;
import com.smart.translator.data.StatsApiService;
import com.smart.translator.util.UserManager;
import java.util.concurrent.CompletableFuture;
import com.smart.translator.data.ApiResponse;
import com.smart.translator.ota.OtaManager;

/**
 * 音频处理器 - 负责BLE音频数据的处理、分帧、重采样、播放、保存等
 * 可以被DeviceFragment和BleManager共享使用
 */
public class AudioProcessor {
    private static final String TAG = "AudioProcessor";
    
    // 音频处理相关
    private AdpcmDecoder adpcmDecoder = new AdpcmDecoder();
    public static final int PCM_SAMPLE_RATE = 8000;
    public static final int PCM_CHANNELS = 1;
    public static final int PCM_BITS = 16;
    
    // v2配置（原有配置）
    public static final int MIN_START_FRAME_SIZE_V2 = 1280;
    public static final int FRAME_SIZE_V2 = 1280;
    public static final int MIN_CHUNK_SIZE_V2 = 1280;
    public static final int SEND_INTERVAL_V2 = 40; // ms
    
    // v3配置（与HTML页面一致）
    public static final int MIN_START_FRAME_SIZE_V3 = 1600;
    public static final int FRAME_SIZE_V3 = 1600;
    public static final int MIN_CHUNK_SIZE_V3 = 1600;
    public static final int SEND_INTERVAL_V3 = 100; // ms
    
    // 动态配置（根据接口版本选择）
    private boolean useSpeechV3 = true;//false; // 默认使用v2
    public static final boolean USE_ASR_CLIENT = true; // 是否使用ASR客户端
    public static final boolean USE_RESAMPLING = true;  // 是否使用重采样（v3模式）
    
    // 音频处理线程
    private java.util.concurrent.ExecutorService audioProcessExecutor = java.util.concurrent.Executors.newSingleThreadExecutor();
    
    // 音频重采样器（单例，避免重复创建）
    private AudioResampler audioResampler;
    
    // 音频处理状态
    private boolean isStartFrameSent = false;
    private boolean isEndFrameSent = false;
    private long lastSendTime = 0;
    private ByteArrayOutputStream pcmBuffer = new ByteArrayOutputStream();
    private ByteArrayOutputStream wavPcmBuffer = new ByteArrayOutputStream();
    
    // 音频缓冲区大小限制
    private static final int MAX_PCM_BUFFER_SIZE = 1024 * 1024; // 1MB限制
    private static final int MAX_WAV_BUFFER_SIZE = 2 * 1024 * 1024; // 2MB限制
    
    // WebSocket相关
    private boolean isWsConnected = false;
    private AsrWsClient asrWsClient;
    private AliyunAsrClient aliyunAsrClient;
    private boolean isAsrConnected = false;
    
    // ASR提供商配置
    private String asrProvider = "doubao"; // 默认使用豆包ASR
    
    // ASR连接超时相关
    private static final long ASR_CONNECT_TIMEOUT = 10000; // 10秒连接超时
    private Handler asrConnectTimeoutHandler = new Handler(Looper.getMainLooper());
    private Runnable asrConnectTimeoutRunnable;
    
    // ASR连接状态管理
    private boolean isAsrConnecting = false; // 是否正在连接中
    private boolean isAsrReadyForAudio = false; // 新增：ASR是否准备好接收音频数据
    
    // ASR时长统计相关
    private long asrStartTime = 0; // ASR开始时间
    private boolean isAsrTiming = false; // 是否正在计时
    private boolean isAsrStatsUploaded = false; // 是否已上传统计数据
    
    // 播放超时相关
    public static final long PLAYBACK_TIMEOUT = 1000; // 1秒超时
    private Handler playbackTimeoutHandler = new Handler(Looper.getMainLooper());
    private Runnable playbackTimeoutRunnable;
    private long lastAudioDataTime = 0;
    
    // 音频数据超时相关（用于断开长时间无数据的ASR连接）
    public static final long AUDIO_DATA_TIMEOUT = 3000; // 1000ms超时
    private Handler audioDataTimeoutHandler = new Handler(Looper.getMainLooper());
    private Runnable audioDataTimeoutRunnable;
    
    // FFF4音频处理相关
    private ByteArrayOutputStream fff4AdpcmBuffer = new ByteArrayOutputStream();
    private ByteArrayOutputStream fff4PcmBuffer = new ByteArrayOutputStream();
    private long lastFFF4DataTime = 0;
    public static final long FFF4_DATA_TIMEOUT = 1000; // 1秒超时
    private Handler fff4TimeoutHandler = new Handler(Looper.getMainLooper());
    private Runnable fff4TimeoutRunnable;
    
    // 识别结果处理
    private StringBuilder recognitionBuffer = new StringBuilder();
    public static final long RECOGNITION_TIMEOUT = 1000; // 1秒超时
    private Handler recognitionHandler = new Handler(Looper.getMainLooper());
    private Runnable recognitionTimeoutRunnable;
    
    // TTS相关
    private DoubaoTTSManager ttsManager;
    private boolean isTtsConnected = false;
    private boolean isTtsConnecting = false; // 新增：TTS是否正在连接中
    
    // 新增：TTS BLE写入相关变量（完全参考DeviceFragment）
    //private static final UUID FFF3_UUID = UUID.fromString("0000fff3-0000-1000-8000-00805f9b34fb");
    private BluetoothGattCharacteristic fff3WriteCharacteristic;
    private BluetoothGatt bluetoothGatt;
    private int adpcmWriteCounter = 0; // ADPCM数据写入序号计数器
    
    // 新增：TTS ADPCM数据缓冲区（参考DeviceFragment）
    private ByteArrayOutputStream ttsAdpcmBuffer = new ByteArrayOutputStream();
    private ByteArrayOutputStream ttsPcmBuffer = new ByteArrayOutputStream();
    private long lastTtsDataTime = 0;
    public static final long TTS_DATA_TIMEOUT = 1000; // 1秒超时
    private Handler ttsTimeoutHandler = new Handler(Looper.getMainLooper());
    private Runnable ttsTimeoutRunnable;
    
    // 新增：TTS文件保存相关
    private byte[] lastTtsPcmData = null;
    private byte[] encodedTtsAdpcmData = null;
    private AdpcmEncoder ttsEncoder = new AdpcmEncoder();
    private AdpcmDecoder ttsDecoder = new AdpcmDecoder();
    
    // VAD相关
    private VadDetector vadDetector;
    private boolean isVadEnabled = false;
    
    // 新增：VAD消息管理（不影响WebSocket发送）
    private boolean isVadSpeechActive = false; // VAD是否检测到语音活动
    private boolean isVadMessageEnded = false; // VAD是否认为消息结束
    private long vadSpeechStartTime = 0; // 语音开始时间
    private long vadLastSpeechTime = 0; // 最后一次检测到语音的时间
    private long vadSilenceStartTime = 0; // 静音开始时间
    private static final long VAD_SILENCE_THRESHOLD = 1000; // 静音阈值（毫秒），超过此时间认为消息结束
    private static final long VAD_SPEECH_MIN_DURATION = 200; // 最小语音持续时间（毫秒）
    private Handler vadMessageHandler = new Handler(Looper.getMainLooper());
    private Runnable vadMessageEndRunnable;
    
    // 消息管理
    private String lastCompletedMessage = ""; // 上一次完成的消息
    private String currentMessage = ""; // 当前正在处理的消息
    private boolean isNewMessageStarted = false; // 是否开始新消息
    
    // 测试相关
    private byte[] lastPcmData = null;
    private byte[] encodedAdpcmData = null;
    private AdpcmEncoder testEncoder = new AdpcmEncoder();
    private AdpcmDecoder testDecoder = new AdpcmDecoder();
    
    // 心跳相关
    private Handler heartbeatHandler = new Handler(Looper.getMainLooper());
    private Runnable heartbeatRunnable;
    public static final long HEARTBEAT_INTERVAL = 30000; // 30秒心跳间隔
    
    // 音频播放相关
    private MediaPlayer mediaPlayer;
    private AudioTrack testAudioTrack;
    private Context context;
    
    // 回调接口
    private AudioProcessorCallback callback;
    
    // UUID常量
    public static final UUID FFF1_UUID = UUID.fromString("0000fff1-0000-1000-8000-00805f9b34fb");
    public static final UUID FFF6_UUID = UUID.fromString("0000fff6-0000-1000-8000-00805f9b34fb");
    public static final UUID FFF4_UUID = UUID.fromString("0000fff4-0000-1000-8000-00805f9b34fb");
    public static final UUID FFF3_UUID = UUID.fromString("0000fff3-0000-1000-8000-00805f9b34fb");
    public static final UUID F2_UUID = UUID.fromString("000000f2-0000-1000-8000-00805f9b34fb");
    
    // 增量显示相关
    private String lastSentToFloatWindow = "";
    
    // 1. 常量区添加
    public static final String ACTION_PAUSE_VOSK_VAD = "com.smart.translator.PAUSE_VOSK_VAD";
    public static final String ACTION_RESUME_VOSK_VAD = "com.smart.translator.RESUME_VOSK_VAD";
    
    // 缓存ASR提供商配置，避免重复读取
    private String cachedAsrProvider = null;
    private long lastAsrProviderCheck = 0;
    private static final long ASR_PROVIDER_CACHE_DURATION = 5000; // 5秒缓存
    
    // 只在VAD状态变化时打印日志
    private boolean lastVadState = false;
    
    public interface AudioProcessorCallback {
        void onAudioDataReceived(byte[] audioData, boolean isEndFrame);
        void onRecognitionResult(String result);
        void onRecognitionResult(String result, boolean isVadFinal);
        void onPcmDataProcessed(byte[] pcmData);
        void onWavDataReady(byte[] wavPcmData);
        void onTtsStatusChanged(boolean connected);
        void onWebSocketStatusChanged(boolean connected);
        void onAudioPlaybackStarted();
        void onAudioPlaybackCompleted();
        void onAudioFileSaved(String filePath);
        void onEncodeTestCompleted(byte[] encodedData);
        void onDecodeTestCompleted(byte[] decodedData);
        void onTtsAdpcmDataReceived(byte[] adpcmData); // 新增：TTS ADPCM数据回调
    }
    
    public AudioProcessor() {
        // 移除自动初始化，改为在首帧时按需初始化
        // 移除自动连接，改为在收到首帧时连接
        // autoConnectServices();
    }
    
    /**
     * 设置上下文（用于文件操作）
     */
    public void setContext(Context context) {
        this.context = context;
    }
    
    /**
     * 设置BLE相关对象（用于TTS ADPCM数据写入）
     */
    public void setBleObjects(BluetoothGatt bluetoothGatt, BluetoothGattCharacteristic fff3WriteCharacteristic) {
        this.bluetoothGatt = bluetoothGatt;
        this.fff3WriteCharacteristic = fff3WriteCharacteristic;
        Log.d(TAG, "BLE对象已设置 - bluetoothGatt: " + (bluetoothGatt != null) + 
                   ", fff3WriteCharacteristic: " + (fff3WriteCharacteristic != null));
    }
    
    /**
     * 设置回调接口
     */
    public void setCallback(AudioProcessorCallback callback) {
        this.callback = callback;
    }
    
    /**
     * 获取动态配置参数
     */
    public int getMinStartFrameSize() {
        return useSpeechV3 ? MIN_START_FRAME_SIZE_V3 : MIN_START_FRAME_SIZE_V2;
    }
    
    public int getFrameSize() {
        return useSpeechV3 ? FRAME_SIZE_V3 : FRAME_SIZE_V2;
    }
    
    public int getMinChunkSize() {
        return useSpeechV3 ? MIN_CHUNK_SIZE_V3 : MIN_CHUNK_SIZE_V2;
    }
    
    public int getSendInterval() {
        return useSpeechV3 ? SEND_INTERVAL_V3 : SEND_INTERVAL_V2;
    }
    
    /**
     * 设置接口版本
     */
    public void setUseSpeechV3(boolean useV3) {
        this.useSpeechV3 = useV3;
        Log.d(TAG, "设置接口版本: " + (useV3 ? "v3" : "v2"));
    }
    
    /**
     * 获取接口版本
     */
    public boolean isUseSpeechV3() {
        return useSpeechV3;
    }
    
    /**
     * 获取ASR连接状态
     */
    public boolean isAsrConnected() {
        return isAsrConnected;
    }
    
    /**
     * 检查ASR WebSocket连接状态（包括内部状态）
     */
    public boolean checkAsrConnectionStatus() {
        boolean wsConnected = false;
        
        // 根据ASR提供商检查对应的客户端连接状态
        if (isDoubaoAsr()) {
            wsConnected = (asrWsClient != null && asrWsClient.isConnected());
        } else if (isAliyunAsr()) {
            wsConnected = (aliyunAsrClient != null && aliyunAsrClient.isConnected());
        }
        
        boolean stateConsistent = (isAsrConnected == wsConnected);
        
        if (!stateConsistent) {
            Log.w(TAG, "ASR连接状态不一致 - isAsrConnected: " + isAsrConnected + 
                       ", wsConnected: " + wsConnected + ", 提供商: " + getAsrProvider());
            // 同步状态
            isAsrConnected = wsConnected;
        }
        
        return isAsrConnected;
    }
    
    /**
     * 获取TTS连接状态
     */
    public boolean isTtsConnected() {
        return isTtsConnected;
    }
    
    /**
     * 检查TTS是否正在连接中
     */
    public boolean isTtsConnecting() {
        return isTtsConnecting;
    }
    
    /**
     * 获取WebSocket连接状态
     */
    public boolean isWsConnected() {
        return isWsConnected;
    }
    
    /**
     * 设置WebSocket连接状态
     */
    public void setWsConnected(boolean connected) {
        this.isWsConnected = connected;
        if (callback != null) {
            callback.onWebSocketStatusChanged(connected);
        }
    }
    
    /**
     * 处理蓝牙音频数据（与DeviceFragment完全一致）
     */
    private long lastBleDataTime = 0;
    public void handleBluetoothData(byte[] data) {
        if (data == null || data.length < 4) return;
        
        // 添加详细的调试日志
        // long currentTime = System.currentTimeMillis();
        // Log.d(TAG, String.format("🔄 handleBluetoothData被调用 - 时间: %d, 数据长度: %d, 线程: %s", 
        //     currentTime, data.length, Thread.currentThread().getName()));
        
        int type = data[3] & 0xFF;
        //  Log.d(TAG, "handleBluetoothData 帧类型: " + type + ", 数据长度: " + data.length);
        
    //     // 更新最后数据时间
    //     lastAudioDataTime = System.currentTimeMillis();


    //     long now = System.currentTimeMillis();
    // if (lastBleDataTime != 0) {
    //             Log.d(TAG, "BLE数据到达, 间隔");

    //     // Log.d(TAG, "BLE数据到达, 间隔: " + (now - lastBleDataTime) + " ms");
    // }
    // lastBleDataTime = now;
        
        // 重置音频数据超时定时器
        resetAudioDataTimeout();
        
        // 解码ADPCM数据
        short[] pcm = adpcmDecoder.decode(data);
        byte[] pcmBytes = shortArrayToByteArray(pcm);
        
        // 将重采样操作移到后台线程，避免阻塞主线程
        if (useSpeechV3 && USE_RESAMPLING) {
            // ⭐ 修复：检查线程池状态，如果已关闭则重新创建
            if (audioProcessExecutor == null || audioProcessExecutor.isShutdown()) {
                Log.d(TAG, "音频处理线程池已关闭，重新创建");
                audioProcessExecutor = java.util.concurrent.Executors.newSingleThreadExecutor();
            }
            
            // 异步处理重采样
            audioProcessExecutor.execute(() -> {
                try {
                    // 使用单例AudioResampler，避免重复创建
                    if (audioResampler == null) {
                        audioResampler = new AudioResampler();
                    }
                    byte[] processedPcmBytes = audioResampler.resample8kTo16k(pcmBytes);
                    //Log.d(TAG, "v3模式重采样: " + pcmBytes.length + " -> " + processedPcmBytes.length + " 字节");
                    
                    // 在主线程中处理后续逻辑
                    new Handler(Looper.getMainLooper()).post(() -> {
                        processAudioData(processedPcmBytes, pcmBytes, type);
                    });
                } catch (Exception e) {
                    Log.e(TAG, "重采样失败，使用原始PCM数据", e);
                    // 在主线程中处理后续逻辑
                    new Handler(Looper.getMainLooper()).post(() -> {
                        processAudioData(pcmBytes, pcmBytes, type);
                    });
                }
            });
        } else {
            // 不需要重采样，直接处理
            processAudioData(pcmBytes, pcmBytes, type);
        }
    }
    
    /**
     * 处理音频数据（在主线程中执行）
     */
    private void processAudioData(byte[] processedPcmBytes, byte[] originalPcmBytes, int type) {
        // 添加调试日志
        // long currentTime = System.currentTimeMillis();
        // Log.d(TAG, String.format("🔄 processAudioData被调用 - 时间: %d, 帧类型: %d, 线程: %s", 
        //     currentTime, type, Thread.currentThread().getName()));
        
        // 追加到WAV缓存（使用原始PCM数据用于播放）
        // try {
        //     wavPcmBuffer.write(originalPcmBytes);
        // } catch (Exception e) {
        //     Log.e(TAG, "WAV PCM数据写入异常", e);
        // }
        
        // 写入缓冲区（v3模式使用重采样后的数据，v2模式使用原始数据）
        appendPcmData(processedPcmBytes);
        
        // 设置播放超时
        //setupPlaybackTimeout();
        
        // 处理帧类型
        processFrameByType(type);
        
        // VAD检测（在ASR发送之前）
        processVadDetection(originalPcmBytes, type);
        
        // 处理ASR发送
        processAsrSending(originalPcmBytes, type);
    }
    
    /**
     * VAD检测处理
     */
    private void processVadDetection(byte[] originalPcmBytes, int type) {
        // 确保VAD检测器已初始化
        if (vadDetector == null) {
            initVadDetector();
        }
        
        if (vadDetector == null) {
            Log.d(TAG, "VAD检测器初始化失败，跳过VAD检测");
            return;
        }
        
        try {
            // 进行VAD检测
            boolean hasSpeech = vadDetector.processAudio(originalPcmBytes);
            
            // 打印VAD检测结果
            String frameTypeStr;
            switch (type) {
                case 0x00:
                    frameTypeStr = "起始帧";
                    break;
                case 0x02:
                    frameTypeStr = "结束帧";
                    break;
                default:
                    frameTypeStr = "中间帧";
                    break;
            }
            
            // Log.d(TAG, String.format("🎤 VAD检测结果 - 帧类型: %s, 数据长度: %d字节, 检测到语音: %s", 
            //     frameTypeStr, originalPcmBytes.length, hasSpeech ? "是" : "否"));
            
            // VAD消息管理（不影响WebSocket发送）
            long currentTime = System.currentTimeMillis();
            
            if (hasSpeech) {
                // 检测到语音活动
                if (!isVadSpeechActive) {
                    // 语音开始
                    isVadSpeechActive = true;
                    isVadMessageEnded = false;
                    vadSpeechStartTime = currentTime;
                    vadSilenceStartTime = 0;
                    Log.d(TAG, "🎤 VAD检测到语音开始");
                    
                    // 检查是否是新消息开始
                    if (isNewMessageStarted) {
                        Log.d(TAG, "🆕 检测到新消息开始");
                        currentMessage = ""; // 清空当前消息
                    }
                    isNewMessageStarted = true;
                }
                
                // 更新最后语音时间
                vadLastSpeechTime = currentTime;
                
                // 检测到语音活动时，停止VAD消息结束定时器
                cancelVadMessageEndTimer();
                
                //Log.d(TAG, "✅ VAD检测到语音，继续ASR处理");
            } else {
                // 检测到静音
                if (isVadSpeechActive) {
                    // 记录静音开始时间
                    if (vadSilenceStartTime == 0) {
                        vadSilenceStartTime = currentTime;
                        Log.d(TAG, "🔇 VAD检测到静音开始");
                        
                        // 第一次检测到静音时，设置VAD消息结束定时器
                        setupVadMessageEndTimer();
                    }
                }
                
                //Log.d(TAG, "🔇 VAD检测到静音，但仍继续ASR处理");
            }
            
        } catch (Exception e) {
            Log.e(TAG, "VAD检测处理失败", e);
        }
    }
    
    /**
     * 根据帧类型处理
     */
    private void processFrameByType(int type) {
        switch (type) {
            case 0x00: // 首帧
                //Log.d(TAG, "收到首帧，重置缓冲区");
                isStartFrameSent = false;
                isEndFrameSent = false;
                pcmBuffer.reset();
                lastSendTime = 0;
                
                // 重置VAD消息状态
                isVadSpeechActive = false;
                isVadMessageEnded = false;
                vadSilenceStartTime = 0;
                cancelVadMessageEndTimer();
                lastCompletedMessage = "";
                currentMessage = "";
                isNewMessageStarted = false;
                Log.d(TAG, "🔄 收到起始帧，重置VAD消息状态");
                
                // 开始ASR计时
                startAsrTiming();
                
                // 收到首帧时，统一连接TTS和ASR两个WebSocket
                Log.d(TAG, "🎯 收到首帧，开始连接TTS和ASR WebSocket");
                connectTTSAndASR();
                
                checkAndSendData();
                // 新增：暂停Vosk VAD
                Intent pauseVoskVad = new Intent(ACTION_PAUSE_VOSK_VAD);
                LocalBroadcastManager.getInstance(context).sendBroadcast(pauseVoskVad);
                break;
            case 0x02: // 结束帧
                Log.d(TAG, "收到结束帧，准备发送结束帧");
                // 取消播放超时
                cancelPlaybackTimeout();
                // 取消音频数据超时
                cancelAudioDataTimeout();
                // 取消VAD消息结束定时器
                cancelVadMessageEndTimer();
                // 先备份WAV数据
                // byte[] wavPcm = wavPcmBuffer.toByteArray();
                sendBufferedData(true);
                // if (wavPcm.length > 0) {
                //     savePcmAsWav(wavPcm);
                // } else {
                //     Log.w(TAG, "结束帧时wavPcmBuffer为空，不保存WAV");
                // }
                // wavPcmBuffer.reset();
                
                // 结束ASR计时并上传统计数据
                stopAsrTimingAndUpload();
                
                // 新增：恢复Vosk VAD
                Intent resumeVoskVad = new Intent(ACTION_RESUME_VOSK_VAD);
                LocalBroadcastManager.getInstance(context).sendBroadcast(resumeVoskVad);
                break;
            default: // 中间帧
                //Log.d(TAG, "中间帧，准备发送中间帧");
                checkAndSendData();
                break;
        }
    }
    
    /**
     * 处理ASR发送
     */
    private void processAsrSending(byte[] originalPcmBytes, int type) {
        // 根据宏控制选择ASR客户端发送逻辑
        if (USE_ASR_CLIENT) {
            // 检查连接状态
            boolean isConnected = checkAsrConnectionStatus();
            
            // 如果v3开关打开且ASR客户端已连接且准备好接收音频数据，将PCM数据发送到ASR客户端
            if (useSpeechV3 && isConnected && isAsrReadyForAudio) {
                boolean isLast = (type == 0x02); // 结束帧
                
                // 根据ASR提供商选择发送到不同的客户端
                if (isDoubaoAsr() && asrWsClient != null) {
                    asrWsClient.sendAudioData(originalPcmBytes, isLast);
                    //Log.d(TAG, "发送PCM数据到豆包ASR客户端，长度: " + originalPcmBytes.length + ", isLast: " + isLast);
                } else if (isAliyunAsr() && aliyunAsrClient != null) {
                    aliyunAsrClient.sendAudioData(originalPcmBytes, isLast);
                    //Log.d(TAG, "发送PCM数据到阿里云ASR客户端，长度: " + originalPcmBytes.length + ", isLast: " + isLast);
                } else {
                    Log.d(TAG, "ASR客户端未初始化或提供商不匹配，音频数据已写入pcmBuffer");
                }
            } else {
                if (!useSpeechV3) {
                    Log.d(TAG, "Speech V3未启用，跳过ASR发送");
                } else if (!isConnected) {
                    Log.d(TAG, "ASR客户端未连接，音频数据已写入pcmBuffer，等待ASR连接成功");
                    // 如果ASR未连接，可以考虑丢弃部分音频数据以避免内存溢出
                    if (pcmBuffer.size() > MAX_PCM_BUFFER_SIZE / 2) {
                        Log.w(TAG, "ASR未连接且缓冲区较大，丢弃部分音频数据");
                        pcmBuffer.reset();
                    }
                } else if (!isAsrReadyForAudio) {
                    Log.d(TAG, "ASR客户端未准备好接收音频数据，音频数据已写入pcmBuffer，等待初始请求完成");
                    // 如果ASR未准备好，可以考虑丢弃部分音频数据以避免内存溢出
                    if (pcmBuffer.size() > MAX_PCM_BUFFER_SIZE / 2) {
                        Log.w(TAG, "ASR未准备好且缓冲区较大，丢弃部分音频数据");
                        pcmBuffer.reset();
                    }
                }
            }
        }
    }
    
    /**
     * 处理FFF4音频数据（与DeviceFragment一致，只用于播放和保存）
     */
    public void handleFFF4AudioData(byte[] adpcmData) {
        if (adpcmData == null || adpcmData.length == 0) {
            Log.w(TAG, "FFF4音频数据为空");
            return;
        }
        
        Log.d(TAG, "开始处理FFF4音频数据，长度: " + adpcmData.length + " 字节");
        
        // 1. 将ADPCM数据追加到缓冲区
        try {
            fff4AdpcmBuffer.write(adpcmData);
            Log.d(TAG, "FFF4 ADPCM数据已追加到缓冲区，当前缓冲区大小: " + fff4AdpcmBuffer.size() + " 字节");
        } catch (Exception e) {
            Log.e(TAG, "FFF4 ADPCM数据写入缓冲区异常", e);
            return;
        }
        
        // 2. 更新最后接收数据时间
        lastFFF4DataTime = System.currentTimeMillis();
        
        // 3. 取消之前的超时任务
        if (fff4TimeoutRunnable != null) {
            fff4TimeoutHandler.removeCallbacks(fff4TimeoutRunnable);
        }
        
        // 4. 设置新的超时任务
        fff4TimeoutRunnable = new Runnable() {
            @Override
            public void run() {
                Log.d(TAG, "FFF4数据接收超时，开始处理完整音频数据");
                processCompleteFFF4Audio();
            }
        };
        fff4TimeoutHandler.postDelayed(fff4TimeoutRunnable, FFF4_DATA_TIMEOUT);
    }
    
    /**
     * 处理完整的FFF4音频数据（与DeviceFragment一致，只用于播放和保存）
     */
    private void processCompleteFFF4Audio() {
        try {
            // 1. 获取完整的ADPCM数据
            byte[] completeAdpcm = fff4AdpcmBuffer.toByteArray();
            if (completeAdpcm.length == 0) {
                Log.w(TAG, "FFF4 ADPCM缓冲区为空，跳过处理");
                return;
            }
            
            Log.d(TAG, "开始处理完整FFF4音频数据，ADPCM长度: " + completeAdpcm.length + " 字节");
            
            // 2. 进行ADPCM解码（无帧头，8K采样率）
            short[] pcmSamples = adpcmDecoder.decodeWithoutHeader(completeAdpcm);
            byte[] pcmData = shortArrayToByteArray(pcmSamples);
            
            Log.d(TAG, "FFF4 ADPCM解码完成，PCM长度: " + pcmData.length + " 字节，采样数: " + pcmSamples.length);
            Log.d(TAG, "FFF4音频采样率: " + PCM_SAMPLE_RATE + " Hz，声道数: " + PCM_CHANNELS + "，位深: " + PCM_BITS + " bit");
            
            // 3. 通知回调
            if (callback != null) {
                callback.onPcmDataProcessed(pcmData);
            }
            
            // 4. 保存PCM数据到文件
            saveFFF4PcmFile(pcmData);
            
            // 5. 保存PCM数据到WAV文件
            saveFFF4PcmAsWav(pcmData);
            
            // 6. 播放音频
            // playFFF4Audio(pcmData);
            
            // 7. 清空缓冲区
            fff4AdpcmBuffer.reset();
            fff4PcmBuffer.reset();
            
            Log.d(TAG, "FFF4音频数据处理完成");
            
        } catch (Exception e) {
            Log.e(TAG, "处理FFF4音频数据异常", e);
        }
    }
    
    /**
     * 处理开始帧
     */
    private void processStartFrame(byte[] data) {
        Log.d(TAG, "处理开始帧");
        isStartFrameSent = false;
        isEndFrameSent = false;
        pcmBuffer.reset();
        // wavPcmBuffer.reset();
        setupPlaybackTimeout();
    }
    
    /**
     * 处理中间帧
     */
    private void processMiddleFrame(byte[] data) {
        if (data.length < 4) return;
        
        // 提取ADPCM数据（跳过前4字节的帧头）
        byte[] adpcmData = new byte[data.length - 4];
        System.arraycopy(data, 4, adpcmData, 0, adpcmData.length);
        
        // 解码ADPCM数据
        short[] pcmShorts = adpcmDecoder.decode(adpcmData);
        byte[] pcmBytes = shortArrayToByteArray(pcmShorts);
        
        // 添加到缓冲区
        appendPcmData(pcmBytes);
        
        // 检查并发送数据
        checkAndSendData();
    }
    
    /**
     * 处理结束帧
     */
    private void processEndFrame(byte[] data) {
        Log.d(TAG, "处理结束帧");
        
        if (data.length >= 4) {
            // 提取ADPCM数据（跳过前4字节的帧头）
            byte[] adpcmData = new byte[data.length - 4];
            System.arraycopy(data, 4, adpcmData, 0, adpcmData.length);
            
            // 解码ADPCM数据
            short[] pcmShorts = adpcmDecoder.decode(adpcmData);
            byte[] pcmBytes = shortArrayToByteArray(pcmShorts);
            
            // 添加到缓冲区
            appendPcmData(pcmBytes);
        }
        
        // 发送结束帧
        sendBufferedData(true);
        
        // 取消播放超时
        cancelPlaybackTimeout();
        
        // 播放当前音频数据
        // playCurrentAudioData();
    }
    
    /**
     * 添加PCM数据到缓冲区
     */
    private void appendPcmData(byte[] pcm) {
        try {
            // 检查缓冲区大小限制
            if (pcmBuffer.size() + pcm.length > MAX_PCM_BUFFER_SIZE) {
                Log.w(TAG, "PCM缓冲区即将溢出，强制发送数据");
                sendBufferedData(false);
            }
            // if (wavPcmBuffer.size() + pcm.length > MAX_WAV_BUFFER_SIZE) {
            //     Log.w(TAG, "WAV缓冲区即将溢出，强制发送数据");
            //     sendBufferedData(false);
            // }
            
            pcmBuffer.write(pcm);
            // wavPcmBuffer.write(pcm);
        } catch (IOException e) {
            Log.e(TAG, "写入PCM缓冲区失败", e);
        }
    }
    
    /**
     * 检查并发送数据
     */
    private void checkAndSendData() {
        long currentTime = System.currentTimeMillis();
        
        // 检查是否达到发送间隔
        if (currentTime - lastSendTime < getSendInterval()) {
            return;
        }
        
        // 检查缓冲区大小
        int bufferSize = pcmBuffer.size();
        int minChunkSize = getMinChunkSize();
        
        if (bufferSize >= minChunkSize) {
            sendBufferedData(false);
        }
    }
    
    /**
     * 发送缓冲数据
     */
    private void sendBufferedData(boolean isEndFrame) {
        if (pcmBuffer.size() == 0) return;
        
        byte[] data = pcmBuffer.toByteArray();
        //Log.d(TAG, "发送缓冲数据，长度: " + data.length + ", isEndFrame: " + isEndFrame);
        
        // 通知回调
        if (callback != null) {
            callback.onAudioDataReceived(data, isEndFrame);
        }
        
        // 清理缓冲区
        pcmBuffer.reset();
        lastSendTime = System.currentTimeMillis();
    }
    
    /**
     * 设置播放超时
     */
    private void setupPlaybackTimeout() {
        if (playbackTimeoutRunnable != null) {
            playbackTimeoutHandler.removeCallbacks(playbackTimeoutRunnable);
        }
        
        playbackTimeoutRunnable = new Runnable() {
            @Override
            public void run() {
                Log.d(TAG, "播放超时，处理当前音频数据");
                // playCurrentAudioData();
            }
        };
        playbackTimeoutHandler.postDelayed(playbackTimeoutRunnable, PLAYBACK_TIMEOUT);
    }
    
    /**
     * 取消播放超时
     */
    private void cancelPlaybackTimeout() {
        if (playbackTimeoutRunnable != null) {
            playbackTimeoutHandler.removeCallbacks(playbackTimeoutRunnable);
        }
    }
    
    /**
     * 播放当前音频数据
     */
    private void playCurrentAudioData() {
        // if (wavPcmBuffer.size() == 0) return;
        
        // byte[] pcmData = wavPcmBuffer.toByteArray();
        // Log.d(TAG, "播放当前音频数据，长度: " + pcmData.length);
        
        // 保存为WAV文件并播放
        // savePcmAsWav(pcmData, false);
        
        // 清理缓冲区
        // wavPcmBuffer.reset();
    }
    
    /**
     * 初始化ASR客户端
     */
    private void initAsrClient() {
        // 清除ASR提供商缓存，确保使用最新配置
        clearAsrProviderCache();
        
        // 如果已经连接，不需要重新初始化
        if (isAsrConnected) {
            Log.d(TAG, "ASR客户端已连接，跳过初始化");
            return;
        }
        
        // 如果正在连接中，跳过重复初始化
        if (isAsrConnecting) {
            Log.d(TAG, "ASR客户端正在连接中，跳过重复初始化");
            return;
        }
        
        // 设置连接状态
        isAsrConnecting = true;
        
        // 获取当前ASR提供商配置
        String currentProvider = getAsrProvider();
        Log.d(TAG, "初始化ASR客户端，当前提供商: " + currentProvider);
        
        // 根据ASR提供商选择初始化不同的客户端
        if (isDoubaoAsr()) {
            Log.d(TAG, "选择初始化豆包ASR客户端");
            initDoubaoAsrClient();
        } else if (isAliyunAsr()) {
            Log.d(TAG, "选择初始化阿里云ASR客户端");
            initAliyunAsrClient();
        } else {
            Log.w(TAG, "未知的ASR提供商: " + currentProvider + "，使用默认豆包ASR");
            initDoubaoAsrClient();
        }
    }
    
    /**
     * 初始化豆包ASR客户端
     */
    private void initDoubaoAsrClient() {
        // 如果客户端存在但未连接，先关闭
        if (asrWsClient != null) {
            asrWsClient.close();
            asrWsClient = null;
        }
        
        // 创建新的豆包ASR客户端
        asrWsClient = new AsrWsClient();
        
        asrWsClient.setCallback(new AsrWsClient.AsrWsCallback() {
            @Override
            public void onConnected() {
                Log.d(TAG, "豆包ASR WebSocket连接成功");
                isAsrConnected = true;
                isAsrConnecting = false; // 重置连接状态
                isAsrReadyForAudio = false; // 重置音频准备状态
                
                // 取消连接超时检查
                cancelAsrConnectTimeout();
                
                // 重置音频缓冲区
                asrWsClient.resetAudioBuffer();
                
                // 延迟50ms发送初始请求，确保WebSocket连接完全稳定
                Log.d(TAG, "豆包ASR连接成功，延迟50ms发送初始请求");
                new Handler(Looper.getMainLooper()).postDelayed(() -> {
                    try {
                        asrWsClient.sendInitialRequest();
                        Log.d(TAG, "豆包ASR初始请求发送调用完成");
                    } catch (Exception e) {
                        Log.e(TAG, "发送豆包ASR初始请求异常", e);
                    }
                }, 50);
                
                // 在主线程中通知回调
                new Handler(Looper.getMainLooper()).post(() -> {
                    if (callback != null) {
                        callback.onWebSocketStatusChanged(true);
                    }
                });
            }
            
            @Override
            public void onInitialRequestSent() {
                Log.d(TAG, "豆包ASR初始请求发送完成，可以开始发送音频数据");
                isAsrReadyForAudio = true;
            }
            
            @Override
            public void onMessage(String text, boolean isFinal) {
                Log.d(TAG, "豆包ASR识别结果: " + text + ", isFinal: " + isFinal);
                // 在主线程中处理识别结果
                new Handler(Looper.getMainLooper()).post(() -> {
                    handleRecognitionResult(text, isFinal);
                });
            }
            
            @Override
            public void onError(String error) {
                Log.e(TAG, "豆包ASR WebSocket错误: " + error);
                isAsrConnected = false;
                isAsrConnecting = false; // 重置连接状态
                isAsrReadyForAudio = false; // 重置音频准备状态
                
                // 取消连接超时检查
                cancelAsrConnectTimeout();
                
                // 在主线程中通知回调
                new Handler(Looper.getMainLooper()).post(() -> {
                    if (callback != null) {
                        callback.onWebSocketStatusChanged(false);
                    }
                });
            }
            
            @Override
            public void onClosed() {
                Log.d(TAG, "豆包ASR WebSocket连接关闭");
                isAsrConnected = false;
                isAsrConnecting = false; // 重置连接状态
                isAsrReadyForAudio = false; // 重置音频准备状态
                
                // 取消连接超时检查
                cancelAsrConnectTimeout();
                
                // 如果正在计时，停止计时并上传统计数据
                if (isAsrTiming) {
                    Log.d(TAG, "ASR连接关闭，停止计时并上传统计数据");
                    stopAsrTimingAndUpload();
                }
                
                // 在主线程中通知回调
                new Handler(Looper.getMainLooper()).post(() -> {
                    if (callback != null) {
                        callback.onWebSocketStatusChanged(false);
                    }
                });
            }
        });
        
        // 连接豆包ASR WebSocket
        Log.d(TAG, "开始连接豆包ASR WebSocket");
        try {
            asrWsClient.connect();
            Log.d(TAG, "豆包ASR WebSocket连接请求已发送");
            
            // 设置连接超时检查
            setupAsrConnectTimeout();
        } catch (Exception e) {
            Log.e(TAG, "豆包ASR WebSocket连接异常", e);
        }
    }
    
    /**
     * 初始化阿里云ASR客户端
     */
    private void initAliyunAsrClient() {
        if (aliyunAsrClient != null) {
            aliyunAsrClient.close();
            aliyunAsrClient = null;
        }
        
        // 从配置中获取WebSocket URL
        String wsUrl = "ws://localhost:8000/ws/aliyun_asr_v2"; // 默认值
        
        try {
            if (context != null) {
                android.content.SharedPreferences prefs = context.getSharedPreferences("app_config", Context.MODE_PRIVATE);
                String configServerUrl = prefs.getString("server_url", "");
                if (!configServerUrl.isEmpty()) {
                    // 构建WebSocket URL
                    wsUrl = "ws://" + configServerUrl + "/ws/aliyun_asr_v2";
                }
            }
        } catch (Exception e) {
            Log.e(TAG, "获取服务器配置失败", e);
        }
        
        Log.d(TAG, "初始化阿里云ASR客户端，WebSocket URL: " + wsUrl);
        
        // aliyunAsrClient = new AliyunAsrClient(wsUrl);

            aliyunAsrClient = new AliyunAsrClient();
            aliyunAsrClient.setUseAliyunDirect(true);
            aliyunAsrClient.setAliyunApiKey("sk-02e1be9ce510429d8c28950a27ac6957");

        aliyunAsrClient.setCallback(new AliyunAsrClient.AliyunAsrCallback() {
            @Override
            public void onConnected() {
                Log.d(TAG, "阿里云ASR WebSocket连接成功");
                isAsrConnected = true;
                isAsrConnecting = false;
                
                
                    // 直连模式下，只有在onInitialRequestSent或task-started后才允许发音频
                if (!aliyunAsrClient.isUseAliyunDirect()) {
                    isAsrReadyForAudio = true;
                    aliyunAsrClient.startRecognition();
                }
                
                if (callback != null) {
                    callback.onWebSocketStatusChanged(true);
                }
                
                // 取消连接超时
                cancelAsrConnectTimeout();
            }
            
            @Override
            public void onInitialRequestSent() {
                Log.d(TAG, "阿里云ASR开始识别请求已发送");
                isAsrReadyForAudio = true;
            }
            
            @Override
            public void onMessage(String text, boolean isFinal) {
                Log.d(TAG, "阿里云ASR识别结果: " + text + ", isFinal: " + isFinal);
                
                // 只处理最终结果，避免重复发送
                if (isFinal && !text.isEmpty()) {
                    if (callback != null) {
                        callback.onRecognitionResult(text, isFinal);
                    }
                    
                    // 处理识别结果
                    handleRecognitionResult(text, isFinal);
                } else if (!isFinal) {
                    Log.d(TAG, "忽略阿里云ASR中间结果: " + text);
                }
            }
            
            @Override
            public void onError(String error) {
                Log.e(TAG, "阿里云ASR错误: " + error);
                isAsrConnected = false;
                isAsrConnecting = false;
                isAsrReadyForAudio = false;
                
                if (callback != null) {
                    callback.onWebSocketStatusChanged(false);
                }
                
                // 取消连接超时
                cancelAsrConnectTimeout();
            }
            
            @Override
            public void onClosed() {
                Log.d(TAG, "阿里云ASR WebSocket连接已关闭");
                isAsrConnected = false;
                isAsrConnecting = false;
                isAsrReadyForAudio = false;
                
                // 如果正在计时，停止计时并上传统计数据
                if (isAsrTiming) {
                    Log.d(TAG, "ASR连接关闭，停止计时并上传统计数据");
                    stopAsrTimingAndUpload();
                }
                
                if (callback != null) {
                    callback.onWebSocketStatusChanged(false);
                }
                
                // 取消连接超时
                cancelAsrConnectTimeout();
            }
        });
        
        // 设置音频配置
        aliyunAsrClient.setAudioConfig(8000/*16000*/, 16, 1); // 16kHz, 16bit, 1ch
        aliyunAsrClient.enableResampling(); // 启用重采样
        
        // 设置识别模型和语言
        aliyunAsrClient.setModel("paraformer-realtime-8k-v2"/*"paraformer-realtime-v2"*/);
        aliyunAsrClient.setLanguageHints(new String[]{"zh", "en"});
        
        // 连接WebSocket
        aliyunAsrClient.connect();
        
        // 设置连接超时
        setupAsrConnectTimeout();
    }
    
    /**
     * 初始化TTS管理器
     */
    private void initTtsManager() {
        if (context != null) {
            ttsManager = new DoubaoTTSManager(context);
            ttsManager.setStateListener(new DoubaoTTSManager.TTSStateListener() {
                @Override
                public void onConnected() {
                    Log.d(TAG, "TTS连接成功");
                    isTtsConnected = true;
                    isTtsConnecting = false; // 重置连接状态
                    if (callback != null) {
                        callback.onTtsStatusChanged(true);
                    }
                }
                
                @Override
                public void onDisconnected() {
                    Log.d(TAG, "TTS连接断开");
                    isTtsConnected = false;
                    isTtsConnecting = false; // 重置连接状态
                    if (callback != null) {
                        callback.onTtsStatusChanged(false);
                    }
                }
                
                @Override
                public void onError(String error) {
                    Log.e(TAG, "TTS错误: " + error);
                    isTtsConnected = false;
                    isTtsConnecting = false; // 重置连接状态
                    if (callback != null) {
                        callback.onTtsStatusChanged(false);
                    }
                }
                
                @Override
                public void onSynthesisComplete() {
                    Log.d(TAG, "TTS合成完成");
                }
            });
            
            // 设置BLE写入回调（完全参考DeviceFragment）
            ttsManager.setBleWriteCallback(new DoubaoTTSManager.BleWriteCallback() {
                @Override
                public void onWriteAdpcmData(byte[] adpcmData) {
                    // 减少日志输出，只在每10次时记录
                    if (adpcmWriteCounter % 10 == 0) {
                        Log.d(TAG, "🎤 TTS ADPCM数据准备发送到BLE: " + adpcmData.length + " 字节");
                    }
                    // 将ADPCM数据写入FFF3特征
                    writeAdpcmDataToFFF3(adpcmData);
                }
            });
            
            // 设置PCM数据回调（完全参考DeviceFragment）
            ttsManager.setPcmDataCallback(new DoubaoTTSManager.PcmDataCallback() {
                @Override
                public void onPcmDataReceived(byte[] pcmData) {
                    Log.d(TAG, "TTS PCM数据: " + pcmData.length + " 字节");
                    
                    // 保存PCM数据用于编码测试（参考DeviceFragment）
                    if (lastTtsPcmData == null) {
                        lastTtsPcmData = pcmData;
                    } else {
                        // 如果已有数据，则追加
                        byte[] combined = new byte[lastTtsPcmData.length + pcmData.length];
                        System.arraycopy(lastTtsPcmData, 0, combined, 0, lastTtsPcmData.length);
                        System.arraycopy(pcmData, 0, combined, lastTtsPcmData.length, pcmData.length);
                        lastTtsPcmData = combined;
                    }
                    Log.d(TAG, "保存TTS PCM数据用于编码测试: " + pcmData.length + " 字节，总计: " + lastTtsPcmData.length + " 字节");
                    
                    // 移除本地播放，只发送到BLE设备
                    // playTtsAudio(pcmData);
                }
            });
            
            // 初始化TTS
            ttsManager.initTTS();
        }
    }
    
    /**
     * 自动连接服务
     */
    private void autoConnectServices() {
        Log.d(TAG, "开始自动连接服务");
        
        // 延迟3秒后自动连接ASR
        new Handler(Looper.getMainLooper()).postDelayed(() -> {
            if (USE_ASR_CLIENT && asrWsClient != null) {
                Log.d(TAG, "自动连接ASR WebSocket");
                connectAsr();
            }
        }, 3000);
        
        // 延迟5秒后自动连接TTS
        new Handler(Looper.getMainLooper()).postDelayed(() -> {
            if (ttsManager != null) {
                Log.d(TAG, "自动连接TTS");
                connectTTS();
            }
        }, 5000);
    }
    
    /**
     * 检查网络连接状态
     */
    private boolean isNetworkAvailable() {
        if (context == null) {
            Log.w(TAG, "Context为空，无法检查网络状态");
            return true; // 假设网络可用
        }
        
        try {
            android.net.ConnectivityManager connectivityManager = 
                (android.net.ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
            if (connectivityManager != null) {
                android.net.NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
                boolean isConnected = activeNetworkInfo != null && activeNetworkInfo.isConnected();
                Log.d(TAG, "网络连接状态: " + isConnected);
                return isConnected;
            }
        } catch (Exception e) {
            Log.e(TAG, "检查网络状态失败", e);
        }
        
        return true; // 默认假设网络可用
    }
    
    /**
     * 连接ASR
     */
    public void connectAsr() {
        if (asrWsClient != null) {
            // 移除网络检查，直接连接（与DeviceFragment保持一致）
            // if (!isNetworkAvailable()) {
            //     Log.w(TAG, "网络不可用，跳过ASR连接");
            //     return;
            // }
            
            asrWsClient.connect();
            Log.d(TAG, "连接ASR WebSocket");
        }
    }
    
    /**
     * 断开ASR
     */
    public void disconnectAsr() {
        Log.d(TAG, "断开ASR连接，提供商: " + getAsrProvider());
        
        // 如果正在计时，停止计时并上传统计数据
        if (isAsrTiming) {
            Log.d(TAG, "ASR断开连接，停止计时并上传统计数据");
            stopAsrTimingAndUpload();
        }
        
        // 根据ASR提供商断开对应的客户端
        if (isDoubaoAsr() && asrWsClient != null) {
            asrWsClient.close();
            Log.d(TAG, "豆包ASR WebSocket已关闭");
        } else if (isAliyunAsr() && aliyunAsrClient != null) {
            aliyunAsrClient.close();
            Log.d(TAG, "阿里云ASR WebSocket已关闭");
        }
        
        // 重置连接状态
        isAsrConnected = false;
        isAsrConnecting = false;
        isAsrReadyForAudio = false; // 重置音频准备状态
        
        // 取消连接超时检查
        cancelAsrConnectTimeout();
        
        // 在主线程中通知回调
        new Handler(Looper.getMainLooper()).post(() -> {
            if (callback != null) {
                callback.onWebSocketStatusChanged(false);
            }
        });
        
        Log.d(TAG, "ASR连接状态已重置");
        // 新增：恢复Vosk VAD
        Intent resumeVoskVad = new Intent(ACTION_RESUME_VOSK_VAD);
        LocalBroadcastManager.getInstance(context).sendBroadcast(resumeVoskVad);
    }
    
    /**
     * 连接TTS
     */
    public void connectTTS() {
        if (ttsManager != null && !isTtsConnected && !isTtsConnecting) {
            Log.d(TAG, "开始连接TTS");
            isTtsConnecting = true; // 设置连接状态
            ttsManager.connect();
        } else if (ttsManager != null && isTtsConnected) {
            Log.d(TAG, "TTS已连接，跳过重复连接");
        } else if (ttsManager != null && isTtsConnecting) {
            Log.d(TAG, "TTS正在连接中，跳过重复连接");
        } else if (ttsManager != null) {
            // TTS管理器存在但状态异常，需要重新初始化
            Log.d(TAG, "TTS管理器状态异常，重新初始化");
            disconnectTTS();
            
            // 添加短暂延迟，确保WebSocket客户端被完全清理
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
            
            initTtsManager();
            if (ttsManager != null) {
                isTtsConnecting = true;
                ttsManager.connect();
            }
        } else {
            Log.w(TAG, "TTS管理器为空，无法连接");
        }
    }
    
    /**
     * 断开TTS
     */
    public void disconnectTTS() {
        if (ttsManager != null) {
            Log.d(TAG, "断开TTS连接");
            ttsManager.disconnect();
            // 重置TTS连接状态
            isTtsConnected = false;
            isTtsConnecting = false;
        }
    }
    
    /**
     * 发送TTS文本
     */
    public void sendTTSText(String text) {
        Log.d(TAG, "🎤 AudioProcessor.sendTTSText被调用: " + text);
        Log.d(TAG, "🎤 TTS状态检查 - ttsManager: " + (ttsManager != null) + ", isTtsConnected: " + isTtsConnected);
        
        if (ttsManager != null && isTtsConnected) {
            Log.d(TAG, "🎤 TTS已连接，开始合成文本: " + text);
            
            // 注释掉文件保存逻辑，提升性能
            // clearAdpcmDataFile();
            // clearRealtimeAdpcmFile();
            // clearBleSentAdpcmFile();
            
            // 重置编码解码测试状态
            lastTtsPcmData = null;
            encodedTtsAdpcmData = null;
            
            ttsManager.synthesizeText(text);
            Log.d(TAG, "✅ TTS文本已发送到合成器: " + text);
        } else {
            if (ttsManager == null) {
                Log.w(TAG, "❌ TTS管理器为空，开始初始化TTS");
                initTtsManager();
            }
            
            if (ttsManager != null && !isTtsConnected) {
                Log.w(TAG, "❌ TTS未连接，开始连接TTS");
                connectTTS();
                
                // 延迟发送文本，等待连接完成
                new Handler(Looper.getMainLooper()).postDelayed(() -> {
                    if (isTtsConnected) {
                        Log.d(TAG, "🎤 TTS连接完成，延迟发送文本: " + text);
                        
                        // 注释掉文件保存逻辑，提升性能
                        // clearAdpcmDataFile();
                        // clearRealtimeAdpcmFile();
                        // clearBleSentAdpcmFile();
                        
                        // 重置编码解码测试状态
                        lastTtsPcmData = null;
                        encodedTtsAdpcmData = null;
                        
                        ttsManager.synthesizeText(text);
                        Log.d(TAG, "✅ 延迟TTS文本已发送到合成器: " + text);
                    } else {
                        Log.w(TAG, "❌ TTS连接失败，无法发送文本: " + text);
                    }
                }, 2000); // 延迟2秒等待连接
            }
        }
    }
    
    /**
     * 开始心跳
     */
    public void startHeartbeat() {
        if (heartbeatRunnable != null) {
            heartbeatHandler.removeCallbacks(heartbeatRunnable);
        }
        
        heartbeatRunnable = new Runnable() {
            @Override
            public void run() {
                sendHeartbeat();
                heartbeatHandler.postDelayed(this, HEARTBEAT_INTERVAL);
            }
        };
        heartbeatHandler.postDelayed(heartbeatRunnable, HEARTBEAT_INTERVAL);
    }
    
    /**
     * 停止心跳
     */
    public void stopHeartbeat() {
        if (heartbeatRunnable != null) {
            heartbeatHandler.removeCallbacks(heartbeatRunnable);
        }
    }
    
    /**
     * 发送心跳
     */
    private void sendHeartbeat() {
        try {
            // 检查OTA状态，如果正在OTA升级则跳过电量读取
            OtaManager otaManager = OtaManager.getInstance();
            if (otaManager != null && (otaManager.getCurrentState() == OtaManager.OTA_STATE_UPDATING || otaManager.isUpdating())) {
                Log.d(TAG, "OTA升级正在进行中，跳过电量读取");
                return;
            }
            
            // 新增：通过BleManager读取设备电池电量
            if (bluetoothGatt != null) {
                BleManager bleManager = BleManager.getInstance();
                if (bleManager != null && bleManager.shouldUpdateBatteryLevel()) {
                    bleManager.readBatteryLevel();
                }
            }
        } catch (Exception e) {
            Log.e(TAG, "发送心跳异常", e);
        }
    }
    
    /**
     * 读取设备电池电量
     */
    private void readBatteryLevel() {
        try {
            if (bluetoothGatt == null) {
                Log.d(TAG, "BLE未连接，跳过电池电量读取");
                return;
            }
            
            // 查找电池服务
            BluetoothGattService batteryService = bluetoothGatt.getService(
                UUID.fromString("0000180f-0000-1000-8000-00805f9b34fb")); // 标准电池服务UUID
            
            if (batteryService == null) {
                Log.d(TAG, "未找到电池服务，跳过电池电量读取");
                return;
            }
            
            // 查找电池电量特征
            BluetoothGattCharacteristic batteryLevelChar = batteryService.getCharacteristic(
                UUID.fromString("00002a19-0000-1000-8000-00805f9b34fb")); // 标准电池电量特征UUID
            
            if (batteryLevelChar == null) {
                Log.d(TAG, "未找到电池电量特征，跳过电池电量读取");
                return;
            }
            
            // 读取电池电量
            boolean success = bluetoothGatt.readCharacteristic(batteryLevelChar);
            if (success) {
                Log.d(TAG, "已发送电池电量读取请求");
            } else {
                Log.w(TAG, "电池电量读取请求失败");
            }
            
        } catch (Exception e) {
            Log.e(TAG, "读取电池电量异常", e);
        }
    }
    
    /**
     * 处理电池电量数据
     */
    public void handleBatteryLevelData(byte[] data) {
        if (data == null || data.length == 0) {
            Log.w(TAG, "电池电量数据为空");
            return;
        }
        
        // 电池电量是0-100的百分比值
        int batteryLevel = data[0] & 0xFF;
        Log.d(TAG, "收到电池电量数据: " + batteryLevel + "%");
        
        // 发送电池电量广播到设备信息界面
        sendBatteryLevelBroadcast(batteryLevel);
    }
    
    /**
     * 发送电池电量广播
     */
    private void sendBatteryLevelBroadcast(int batteryLevel) {
        try {
            Intent intent = new Intent("com.smart.translator.BATTERY_LEVEL_UPDATE");
            intent.putExtra("battery_level", batteryLevel);
            intent.putExtra("timestamp", System.currentTimeMillis());
            context.sendBroadcast(intent);
            Log.d(TAG, "已发送电池电量广播: " + batteryLevel + "%");
        } catch (Exception e) {
            Log.e(TAG, "发送电池电量广播失败", e);
        }
    }
    
    /**
     * 处理识别结果（只显示最终结果）
     */
    private void handleRecognitionResult(String text, boolean isFinal) {
        Log.d(TAG, "处理识别结果: " + text + ", isFinal: " + isFinal);
        if (!text.isEmpty() && isFinal) {
            if (callback != null) {
                callback.onRecognitionResult(text, true);
            }
            // 更新消息状态
            currentMessage = text;
            lastSentToFloatWindow = text; // 更新最后一次发送的文本，用于VAD最终结果
            Log.d(TAG, "📝 更新识别文本 - currentMessage: '" + currentMessage + "', lastSentToFloatWindow: '" + lastSentToFloatWindow + "'");
        } else if (text.isEmpty()) {
            Log.w(TAG, "收到空的ASR识别结果，跳过处理");
        } else {
            Log.d(TAG, "忽略中间ASR结果: " + text);
        }
        // 不再为中间结果设置识别超时定时器
        if (recognitionTimeoutRunnable != null) {
            recognitionHandler.removeCallbacks(recognitionTimeoutRunnable);
        }
    }
    
    /**
     * VAD静音超时，发送最终完整内容到悬浮窗
     */
    private void setupVadMessageEndTimer() {
        if (vadMessageEndRunnable != null) {
            vadMessageHandler.removeCallbacks(vadMessageEndRunnable);
        }
        vadMessageEndRunnable = new Runnable() {
            @Override
            public void run() {
                Log.d(TAG, "⏰ VAD静音超时1000ms，认为消息结束");
                Log.d(TAG, "当前状态 - currentMessage: '" + currentMessage + "', lastSentToFloatWindow: '" + lastSentToFloatWindow + "'");
                
                // 使用currentMessage作为最终结果
                String finalText = currentMessage;
                if (finalText.isEmpty() && !lastSentToFloatWindow.isEmpty()) {
                    finalText = lastSentToFloatWindow;
                    Log.d(TAG, "currentMessage为空，使用lastSentToFloatWindow: " + finalText);
                }
                
                if (!finalText.isEmpty()) {
                    lastCompletedMessage = finalText;
                    lastSentToFloatWindow = finalText; // 更新基准
                    Log.d(TAG, "💾 保存完成的消息: " + lastCompletedMessage);
                    
                    // 发送最终完整内容到悬浮窗
                    if (!isAliyunAsr()) {
                        if (callback != null) {
                            Log.d(TAG, "📤 发送VAD最终结果到悬浮窗: " + finalText);
                            callback.onRecognitionResult(finalText, true); // 标记为VAD最终结果
                        } else {
                            Log.w(TAG, "❌ callback为空，无法发送VAD最终结果");
                        }
                    } else {
                        Log.d(TAG, "Aliyun ASR，VAD静音超时不回调最终结果，避免重复");
                    }
                } else {
                    Log.w(TAG, "❌ VAD最终结果为空，跳过发送");
                }
                
                // 重置VAD状态
                isVadSpeechActive = false;
                isVadMessageEnded = true;
                vadSilenceStartTime = 0;
                
                // 发送VAD状态广播
                sendVadStateBroadcast(false);
            }
        };
        vadMessageHandler.postDelayed(vadMessageEndRunnable, VAD_SILENCE_THRESHOLD);
        Log.d(TAG, String.format("⏰ 设置VAD消息结束定时器: %dms", VAD_SILENCE_THRESHOLD));
    }
    
    /**
     * 获取新内容（与上一次发送到悬浮窗的内容对比）
     */
    private String getNewContent(String currentText, String lastSent) {
        if (lastSent.isEmpty()) return currentText;
        if (currentText.startsWith(lastSent)) {
            return currentText.substring(lastSent.length());
        }
        return currentText;
    }
    
    /**
     * 短整型数组转字节数组
     */
    private byte[] shortArrayToByteArray(short[] arr) {
        byte[] bytes = new byte[arr.length * 2];
        for (int i = 0; i < arr.length; i++) {
            bytes[i * 2] = (byte) (arr[i] & 0xFF);
            bytes[i * 2 + 1] = (byte) ((arr[i] >> 8) & 0xFF);
        }
        return bytes;
    }
    
    /**
     * 清理资源
     */
    public void cleanup() {
        Log.d(TAG, "清理AudioProcessor资源");
        
        // 如果正在计时，停止计时并上传统计数据
        if (isAsrTiming) {
            Log.d(TAG, "AudioProcessor清理，停止计时并上传统计数据");
            stopAsrTimingAndUpload();
        }
        
        // 停止心跳
        stopHeartbeat();
        
        // 取消所有定时器
        if (playbackTimeoutRunnable != null) {
            playbackTimeoutHandler.removeCallbacks(playbackTimeoutRunnable);
        }
        if (fff4TimeoutRunnable != null) {
            fff4TimeoutHandler.removeCallbacks(fff4TimeoutRunnable);
        }
        if (recognitionTimeoutRunnable != null) {
            recognitionHandler.removeCallbacks(recognitionTimeoutRunnable);
        }
        if (audioDataTimeoutRunnable != null) {
            audioDataTimeoutHandler.removeCallbacks(audioDataTimeoutRunnable);
        }
        if (asrConnectTimeoutRunnable != null) {
            asrConnectTimeoutHandler.removeCallbacks(asrConnectTimeoutRunnable);
        }
        if (vadMessageEndRunnable != null) {
            vadMessageHandler.removeCallbacks(vadMessageEndRunnable);
        }
        if (ttsTimeoutRunnable != null) {
            ttsTimeoutHandler.removeCallbacks(ttsTimeoutRunnable);
        }
        
        // 关闭ASR客户端
        if (isDoubaoAsr() && asrWsClient != null) {
            asrWsClient.close();
            Log.d(TAG, "豆包ASR客户端已关闭");
        } else if (isAliyunAsr() && aliyunAsrClient != null) {
            aliyunAsrClient.close();
            Log.d(TAG, "阿里云ASR客户端已关闭");
        }
        
        // 重置ASR连接状态
        isAsrConnected = false;
        isAsrConnecting = false;
        
        // 断开TTS
        if (ttsManager != null) {
            ttsManager.disconnect();
            // 重置TTS连接状态
            isTtsConnected = false;
            isTtsConnecting = false;
        }
        
        // 释放音频播放器
        if (mediaPlayer != null) {
            mediaPlayer.release();
            mediaPlayer = null;
        }
        
        if (testAudioTrack != null) {
            testAudioTrack.release();
            testAudioTrack = null;
        }
        
        // 清理缓冲区
        pcmBuffer.reset();
        // wavPcmBuffer.reset();
        fff4AdpcmBuffer.reset();
        fff4PcmBuffer.reset();
        ttsAdpcmBuffer.reset();
        ttsPcmBuffer.reset();
        recognitionBuffer.setLength(0);
        
        // 重置VAD消息状态
        lastCompletedMessage = "";
        currentMessage = "";
        isNewMessageStarted = false;
        
        // 重置TTS相关状态
        lastTtsPcmData = null;
        encodedTtsAdpcmData = null;
        adpcmWriteCounter = 0;
        
        // ⭐ 修复：关闭音频处理线程池
        if (audioProcessExecutor != null && !audioProcessExecutor.isShutdown()) {
            audioProcessExecutor.shutdown();
            try {
                if (!audioProcessExecutor.awaitTermination(5, java.util.concurrent.TimeUnit.SECONDS)) {
                    audioProcessExecutor.shutdownNow();
                }
            } catch (InterruptedException e) {
                audioProcessExecutor.shutdownNow();
            }
            // ⭐ 修复：将线程池设置为null，以便重新创建
            audioProcessExecutor = null;
        }
        
        Log.d(TAG, "AudioProcessor资源清理完成");
    }
    
    // ==================== 音频播放功能 ====================
    
    /**
     * 播放PCM音频数据
     */
    public void playPcmAudio(byte[] pcmData) {
        // 注释掉所有播放逻辑
        /*
        if (pcmData == null || pcmData.length == 0) return;
        
        try {
            // 创建AudioTrack
            int bufferSize = AudioTrack.getMinBufferSize(
                PCM_SAMPLE_RATE, 
                AudioFormat.CHANNEL_OUT_MONO, 
                AudioFormat.ENCODING_PCM_16BIT
            );
            
            if (testAudioTrack != null) {
                testAudioTrack.release();
            }
            
            testAudioTrack = new AudioTrack.Builder()
                .setAudioAttributes(new android.media.AudioAttributes.Builder()
                    .setUsage(android.media.AudioAttributes.USAGE_MEDIA)
                    .setContentType(android.media.AudioAttributes.CONTENT_TYPE_SPEECH)
                    .build())
                .setAudioFormat(new AudioFormat.Builder()
                    .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
                    .setSampleRate(PCM_SAMPLE_RATE)
                    .setChannelMask(AudioFormat.CHANNEL_OUT_MONO)
                    .build())
                .setBufferSizeInBytes(bufferSize)
                .setTransferMode(AudioTrack.MODE_STREAM)
                .build();
            
            testAudioTrack.play();
            testAudioTrack.write(pcmData, 0, pcmData.length);
            
            if (callback != null) {
                callback.onAudioPlaybackStarted();
            }
            
            Log.d(TAG, "PCM音频播放开始，长度: " + pcmData.length);
            
        } catch (Exception e) {
            Log.e(TAG, "播放PCM音频失败", e);
        }
        */
    }
    
    /**
     * 播放TTS音频
     */
    public void playTtsAudio(byte[] pcmData) {
        // 注释掉播放逻辑
        // playPcmAudio(pcmData);
    }
    
    /**
     * 播放FFF4音频
     */
    public void playFFF4Audio(byte[] pcmData) {
        // 注释掉播放逻辑
        // playPcmAudio(pcmData);
    }
    
    /**
     * 播放WAV文件
     */
    public void playWavFile(File wavFile) {
        // 注释掉播放逻辑
        /*
        if (wavFile == null || !wavFile.exists()) {
            Log.e(TAG, "WAV文件不存在");
            return;
        }
        
        try {
            if (mediaPlayer != null) {
                mediaPlayer.release();
            }
            
            mediaPlayer = new MediaPlayer();
            mediaPlayer.setDataSource(wavFile.getAbsolutePath());
            mediaPlayer.prepare();
            mediaPlayer.start();
            
            if (callback != null) {
                callback.onAudioPlaybackStarted();
            }
            
            Log.d(TAG, "WAV文件播放开始: " + wavFile.getName());
            
        } catch (Exception e) {
            Log.e(TAG, "播放WAV文件失败", e);
        }
        */
    }
    
    // ==================== 文件保存功能 ====================
    
    /**
     * 保存PCM为WAV文件
     */
    public void savePcmAsWav(byte[] pcmData) {
        savePcmAsWav(pcmData, false);
    }
    
    /**
     * 保存PCM为WAV文件
     */
    public void savePcmAsWav(byte[] pcmData, boolean isTimeoutPlayback) {
        if (context == null || pcmData == null || pcmData.length == 0) return;
        
        try {
            String fileName = "audio_" + System.currentTimeMillis() + 
                (isTimeoutPlayback ? "_timeout" : "") + ".wav";
            File file = new File(context.getExternalFilesDir(null), fileName);
            
            byte[] wavData = WavUtil.pcmToWav(pcmData, PCM_SAMPLE_RATE, PCM_CHANNELS, PCM_BITS);
            
            FileOutputStream fos = new FileOutputStream(file);
            fos.write(wavData);
            fos.close();
            
            Log.d(TAG, "WAV文件保存成功: " + file.getAbsolutePath());
            
            if (callback != null) {
                callback.onAudioFileSaved(file.getAbsolutePath());
            }
            
            // 如果是超时播放，自动播放文件
            if (isTimeoutPlayback) {
                // playWavFile(file);
            }
            
        } catch (Exception e) {
            Log.e(TAG, "保存WAV文件失败", e);
        }
    }
    
    /**
     * 保存FFF4 PCM为WAV文件
     */
    public void saveFFF4PcmAsWav(byte[] pcmData) {
        if (context == null || pcmData == null || pcmData.length == 0) return;
        
        try {
            String fileName = "fff4_audio_" + System.currentTimeMillis() + ".wav";
            File file = new File(context.getExternalFilesDir(null), fileName);
            
            byte[] wavData = WavUtil.pcmToWav(pcmData, PCM_SAMPLE_RATE, PCM_CHANNELS, PCM_BITS);
            
            FileOutputStream fos = new FileOutputStream(file);
            fos.write(wavData);
            fos.close();
            
            Log.d(TAG, "FFF4 WAV文件保存成功: " + file.getAbsolutePath());
            
            if (callback != null) {
                callback.onAudioFileSaved(file.getAbsolutePath());
            }
            
        } catch (Exception e) {
            Log.e(TAG, "保存FFF4 WAV文件失败", e);
        }
    }
    
    /**
     * 保存PCM文件
     */
    public void savePcmFile(byte[] pcmData, String fileName) {
        if (context == null || pcmData == null || pcmData.length == 0) return;
        
        try {
            File file = new File(context.getExternalFilesDir(null), fileName);
            
            FileOutputStream fos = new FileOutputStream(file);
            fos.write(pcmData);
            fos.close();
            
            Log.d(TAG, "PCM文件保存成功: " + file.getAbsolutePath());
            
            if (callback != null) {
                callback.onAudioFileSaved(file.getAbsolutePath());
            }
            
        } catch (Exception e) {
            Log.e(TAG, "保存PCM文件失败", e);
        }
    }
    
    /**
     * 保存ADPCM文件
     */
    public void saveAdpcmFile(byte[] adpcmData, String fileName) {
        if (context == null || adpcmData == null || adpcmData.length == 0) return;
        
        try {
            File file = new File(context.getExternalFilesDir(null), fileName);
            
            FileOutputStream fos = new FileOutputStream(file);
            fos.write(adpcmData);
            fos.close();
            
            Log.d(TAG, "ADPCM文件保存成功: " + file.getAbsolutePath());
            
            if (callback != null) {
                callback.onAudioFileSaved(file.getAbsolutePath());
            }
            
        } catch (Exception e) {
            Log.e(TAG, "保存ADPCM文件失败", e);
        }
    }
    
    // ==================== 编码/解码测试功能 ====================
    
    /**
     * 执行编码测试
     */
    public void performEncodeTest(byte[] pcmData) {
        if (pcmData == null || pcmData.length == 0) return;
        
        try {
            Log.d(TAG, "开始编码测试，PCM长度: " + pcmData.length);
            
            // 将字节数组转换为短整型数组
            short[] pcmShorts = new short[pcmData.length / 2];
            for (int i = 0; i < pcmShorts.length; i++) {
                pcmShorts[i] = (short) ((pcmData[i * 2] & 0xFF) | (pcmData[i * 2 + 1] << 8));
            }
            
            // 编码为ADPCM
            byte[] encodedData = testEncoder.encode(pcmShorts);
            
            Log.d(TAG, "编码测试完成，ADPCM长度: " + encodedData.length);
            
            // 保存测试结果
            lastPcmData = pcmData;
            encodedAdpcmData = encodedData;
            
            // 保存测试文件
            saveTestPcmFile(pcmData, "test_input.pcm");
            saveTestAdpcmFile(encodedData, "test_encoded.adpcm");
            saveTestPcmAsWav(pcmData, "test_input.wav");
            
            if (callback != null) {
                callback.onEncodeTestCompleted(encodedData);
            }
            
        } catch (Exception e) {
            Log.e(TAG, "编码测试失败", e);
        }
    }
    
    /**
     * 执行解码测试
     */
    public void performDecodeTest(byte[] adpcmData) {
        if (adpcmData == null || adpcmData.length == 0) return;
        
        try {
            Log.d(TAG, "开始解码测试，ADPCM长度: " + adpcmData.length);
            
            // 解码ADPCM数据
            short[] pcmShorts = testDecoder.decode(adpcmData);
            byte[] decodedData = shortArrayToByteArray(pcmShorts);
            
            Log.d(TAG, "解码测试完成，PCM长度: " + decodedData.length);
            
            // 保存测试文件
            saveTestPcmFile(decodedData, "test_decoded.pcm");
            saveTestPcmAsWav(decodedData, "test_decoded.wav");
            
            // 播放解码后的音频
            // playDecodedAudio(decodedData);
            
            if (callback != null) {
                callback.onDecodeTestCompleted(decodedData);
            }
            
        } catch (Exception e) {
            Log.e(TAG, "解码测试失败", e);
        }
        
    }
    
    /**
     * 播放解码后的音频
     */
    public void playDecodedAudio(byte[] pcmData) {
        // 注释掉播放逻辑
        // playPcmAudio(pcmData);
    }
    
    /**
     * 保存测试PCM文件
     */
    private void saveTestPcmFile(byte[] pcmData, String fileName) {
        savePcmFile(pcmData, fileName);
    }
    
    /**
     * 保存测试ADPCM文件
     */
    private void saveTestAdpcmFile(byte[] adpcmData, String fileName) {
        saveAdpcmFile(adpcmData, fileName);
    }
    
    /**
     * 保存测试WAV文件
     */
    private void saveTestPcmAsWav(byte[] pcmData, String fileName) {
        if (context == null || pcmData == null || pcmData.length == 0) return;
        
        try {
            File file = new File(context.getExternalFilesDir(null), fileName);
            
            byte[] wavData = WavUtil.pcmToWav(pcmData, PCM_SAMPLE_RATE, PCM_CHANNELS, PCM_BITS);
            
            FileOutputStream fos = new FileOutputStream(file);
            fos.write(wavData);
            fos.close();
            
            Log.d(TAG, "测试WAV文件保存成功: " + file.getAbsolutePath());
            
        } catch (Exception e) {
            Log.e(TAG, "保存测试WAV文件失败", e);
        }
    }
    
    // ==================== 获取测试数据 ====================
    
    /**
     * 获取最后的PCM数据
     */
    public byte[] getLastPcmData() {
        return lastPcmData;
    }
    
    /**
     * 获取编码后的ADPCM数据
     */
    public byte[] getEncodedAdpcmData() {
        return encodedAdpcmData;
    }
    
    /**
     * 获取ADPCM写入计数器
     */
    public int getAdpcmWriteCounter() {
        return adpcmWriteCounter;
    }
    
    /**
     * 重置ADPCM写入计数器
     */
    public void resetAdpcmWriteCounter() {
        adpcmWriteCounter = 0;
    }
    
    /**
     * 发送结束信号给ASR（用于通知音频流结束）
     */
    public void sendEndSignalToAsr() {
        if (useSpeechV3 && isAsrConnected) {
            Log.d(TAG, "发送结束信号给ASR服务，提供商: " + getAsrProvider());
            
            // 根据ASR提供商发送结束信号到对应的客户端
            if (isDoubaoAsr() && asrWsClient != null && asrWsClient.canSendAudioData()) {
                asrWsClient.sendAudioData(new byte[0], true); // 发送空数据表示结束
                Log.d(TAG, "已发送结束信号给豆包ASR");
            } else if (isAliyunAsr() && aliyunAsrClient != null /*&& aliyunAsrClient.canSendAudioData()*/) {
                aliyunAsrClient.stopRecognition(); // 停止识别
                Log.d(TAG, "已发送停止识别信号给阿里云ASR");
            } else {
                Log.d(TAG, "ASR客户端不可用，跳过结束信号发送");
            }
        } else {
            Log.d(TAG, "ASR服务不可用，跳过结束信号发送");
        }
    }
    
    /**
     * 保存FFF4 PCM数据为PCM文件（与DeviceFragment一致）
     */
    public void saveFFF4PcmFile(byte[] pcmData) {
        if (context == null || pcmData == null || pcmData.length == 0) return;
        
        try {
            // 保存到外部存储的包名目录下，使用固定文件名（新文件替换旧文件）
            File pcmFile = new File(context.getExternalFilesDir(null), "fff4_audio.pcm");
            FileOutputStream fos = new FileOutputStream(pcmFile);
            fos.write(pcmData);
            fos.close();
            Log.d(TAG, "FFF4 PCM文件已保存: " + pcmFile.getAbsolutePath());
            Log.d(TAG, "FFF4 PCM文件大小: " + pcmData.length + " 字节");
            
            if (callback != null) {
                callback.onAudioFileSaved(pcmFile.getAbsolutePath());
            }
        } catch (Exception e) {
            Log.e(TAG, "保存FFF4 PCM文件异常", e);
        }
    }
    
    /**
     * 重置音频数据超时定时器
     */
    private void resetAudioDataTimeout() {

        long now = System.currentTimeMillis();
        //Log.d(TAG, "resetAudioDataTimeout 设置定时器, now=" + now);

        if (audioDataTimeoutRunnable != null) {
            audioDataTimeoutHandler.removeCallbacks(audioDataTimeoutRunnable);
        }
        
        audioDataTimeoutRunnable = new Runnable() {
            @Override
            public void run() {


                  long trigger = System.currentTimeMillis();
                Log.d(TAG, "音频数据超时，定时器触发, trigger=" + trigger + ", 距上次设置: " + (trigger - now) + " ms");
                //Log.d(TAG, "音频数据超时，准备断开ASR连接");
                
                // 检查连接状态
                boolean isConnected = checkAsrConnectionStatus();
                
                // 如果ASR已连接，先发送结束信号
                if (useSpeechV3 && isConnected) {
                    Log.d(TAG, "发送结束信号给ASR服务，提供商: " + getAsrProvider());
                    
                    // 根据ASR提供商发送结束信号到对应的客户端
                    if (isDoubaoAsr() && asrWsClient != null && asrWsClient.canSendAudioData()) {
                        asrWsClient.sendAudioData(new byte[0], true); // 发送空数据表示结束
                        Log.d(TAG, "已发送结束信号给豆包ASR");
                    } else if (isAliyunAsr() && aliyunAsrClient != null  /*&& aliyunAsrClient.canSendAudioData()*/) {
                        aliyunAsrClient.stopRecognition(); // 停止识别
                        Log.d(TAG, "已发送停止识别信号给阿里云ASR");
                    } else {
                        Log.d(TAG, "ASR客户端不可用，跳过结束信号发送");
                    }
                    
                    // 延迟断开连接，给ASR服务时间处理结束信号
                    new Handler(Looper.getMainLooper()).postDelayed(() -> {
                        Log.d(TAG, "延迟断开ASR连接");
                        disconnectAsr();
                    }, 500); // 延迟500ms
                } else {
                    // 直接断开连接
                    disconnectAsr();
                }
            }
        };
        audioDataTimeoutHandler.postDelayed(audioDataTimeoutRunnable, AUDIO_DATA_TIMEOUT);
    }
    
    /**
     * 取消音频数据超时
     */
    private void cancelAudioDataTimeout() {
        if (audioDataTimeoutRunnable != null) {
            audioDataTimeoutHandler.removeCallbacks(audioDataTimeoutRunnable);
        }
    }
    
    /**
     * 设置ASR连接超时检查
     */
    private void setupAsrConnectTimeout() {
        if (asrConnectTimeoutRunnable != null) {
            asrConnectTimeoutHandler.removeCallbacks(asrConnectTimeoutRunnable);
        }
        
        asrConnectTimeoutRunnable = new Runnable() {
            @Override
            public void run() {
                Log.w(TAG, "ASR连接超时，重置连接状态，提供商: " + getAsrProvider());
                isAsrConnecting = false; // 重置连接状态
                if (!isAsrConnected) {
                    Log.w(TAG, "ASR连接超时，关闭WebSocket连接");
                    
                    // 根据ASR提供商关闭对应的客户端连接
                    if (isDoubaoAsr() && asrWsClient != null) {
                        asrWsClient.close();
                        Log.d(TAG, "豆包ASR WebSocket已关闭");
                    } else if (isAliyunAsr() && aliyunAsrClient != null) {
                        aliyunAsrClient.close();
                        Log.d(TAG, "阿里云ASR WebSocket已关闭");
                    }
                }
            }
        };
        asrConnectTimeoutHandler.postDelayed(asrConnectTimeoutRunnable, ASR_CONNECT_TIMEOUT);
    }
    
    /**
     * 取消ASR连接超时检查
     */
    private void cancelAsrConnectTimeout() {
        if (asrConnectTimeoutRunnable != null) {
            asrConnectTimeoutHandler.removeCallbacks(asrConnectTimeoutRunnable);
        }
    }
    
    /**
     * 强制清理ASR连接（用于异常情况）
     */
    public void forceCleanupAsr() {
        Log.w(TAG, "强制清理ASR连接，提供商: " + getAsrProvider());
        
        // 取消所有相关定时器
        cancelAudioDataTimeout();
        cancelAsrConnectTimeout();
        
        // 根据ASR提供商关闭对应的客户端连接
        if (isDoubaoAsr() && asrWsClient != null) {
            try {
                asrWsClient.close();
                Log.d(TAG, "豆包ASR WebSocket已强制关闭");
            } catch (Exception e) {
                Log.e(TAG, "强制关闭豆包ASR WebSocket异常", e);
            }
            asrWsClient = null;
        } else if (isAliyunAsr() && aliyunAsrClient != null) {
            try {
                aliyunAsrClient.close();
                Log.d(TAG, "阿里云ASR WebSocket已强制关闭");
            } catch (Exception e) {
                Log.e(TAG, "强制关闭阿里云ASR WebSocket异常", e);
            }
            aliyunAsrClient = null;
        }
        
        // 重置所有状态
        isAsrConnected = false;
        isAsrConnecting = false;
        isAsrReadyForAudio = false; // 重置音频准备状态
        
        // 清理缓冲区
        if (pcmBuffer != null) {
            pcmBuffer.reset();
        }
        
        // 在主线程中通知回调
        new Handler(Looper.getMainLooper()).post(() -> {
            if (callback != null) {
                callback.onWebSocketStatusChanged(false);
            }
        });
        
        Log.d(TAG, "ASR连接已强制清理完成");
    }
    
    /**
     * 初始化VAD检测器
     */
    private void initVadDetector() {
        try {
            // 设置VAD类型为WebRTC（与原来保持一致）
            VadDetector.setVadType(VadDetector.VadType.WEBRTC);
            
            vadDetector = new VadDetector(context);
            
            // 设置VAD回调
            vadDetector.setCallback(new VadDetector.VadCallback() {
                @Override
                public void onSpeechStart() {
                    Log.d(TAG, "🎤 VAD检测到语音开始");
                    sendVadStateBroadcast(true);
                }
                
                @Override
                public void onSpeechEnd() {
                    Log.d(TAG, "🔇 VAD检测到语音结束");
                    sendVadStateBroadcast(false);
                }
                
                @Override
                public void onVoiceActivity(boolean isSpeech) {
                    // 只在状态变化时打印
                    if (isSpeech != lastVadState) {
                        if (isSpeech) {
                            Log.d(TAG, "🎵 VAD检测到语音活动");
                        } else {
                            Log.d(TAG, "🔇 VAD检测到静音");
                        }
                        lastVadState = isSpeech;
                    }
                }
                
                @Override
                public void onVadError(String error) {
                    Log.e(TAG, "VAD错误: " + error);
                }
            });
            
            // 初始化VAD检测器（8kHz采样率，使用原来的帧大小160）
            vadDetector.initialize(PCM_SAMPLE_RATE, 160); // 20ms帧大小 @ 8kHz (160样本)
            isVadEnabled = true;
            
            Log.d(TAG, "✅ VAD检测器初始化成功");
            
        } catch (Exception e) {
            Log.e(TAG, "❌ VAD检测器初始化失败", e);
            isVadEnabled = false;
        }
    }
    
    // 新增：发送VAD说话状态广播
    private void sendVadStateBroadcast(boolean isSpeaking) {
        try {
            Intent intent = new Intent("com.smart.translator.VAD_STATE");
            intent.putExtra("is_speaking", isSpeaking);
            LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
        } catch (Exception e) {
            Log.e(TAG, "发送VAD说话状态广播失败", e);
        }
    }
    
    /**
     * 取消VAD消息结束定时器
     */
    private void cancelVadMessageEndTimer() {
        if (vadMessageEndRunnable != null) {
            vadMessageHandler.removeCallbacks(vadMessageEndRunnable);
        }
    }
    
    /**
     * 统一连接TTS和ASR两个WebSocket
     */
    private void connectTTSAndASR() {
        Log.d(TAG, "🎯 开始统一连接TTS和ASR WebSocket");
        
        // 1. 处理TTS连接
        if (ttsManager == null) {
            Log.d(TAG, "🎤 初始化TTS管理器");
            initTtsManager();
        }
        if (ttsManager != null && !isTtsConnected && !isTtsConnecting) {
            Log.d(TAG, "🎤 连接TTS WebSocket");
            connectTTS();
        } else if (ttsManager != null && isTtsConnecting) {
            Log.d(TAG, "🎤 TTS正在连接中，跳过重复连接");
        } else if (ttsManager != null && isTtsConnected) {
            Log.d(TAG, "🎤 TTS已连接，跳过重复连接");
        }
        
        // 2. 处理ASR连接
        if (USE_ASR_CLIENT) {
            if (useSpeechV3 && (asrWsClient == null || !isAsrConnected)) {
                if (!isAsrConnecting) {
                    Log.d(TAG, "🎵 连接ASR WebSocket");
                    initAsrClient();
                } else {
                    Log.d(TAG, "🎵 ASR正在连接中，跳过重复连接");
                }
            } else if (useSpeechV3 && isAsrConnected) {
                Log.d(TAG, "🎵 ASR已连接，跳过重复连接");
            } else if (!useSpeechV3) {
                Log.d(TAG, "🎵 Speech V3未启用，跳过ASR连接");
            }
        } else {
            Log.d(TAG, "🎵 ASR客户端未启用，跳过ASR连接");
        }
        
        Log.d(TAG, "🎯 TTS和ASR WebSocket连接请求已发送");
    }
    
    /**
     * 将ADPCM数据写入FFF3特征（优化版本，移除文件保存，提升性能）
     * @param adpcmData ADPCM编码的音频数据
     */
    private void writeAdpcmDataToFFF3(byte[] adpcmData) {
        try {
            if (fff3WriteCharacteristic == null) {
                Log.e(TAG, "FFF3写特征未找到，无法发送ADPCM数据");
                return;
            }
            
            if (bluetoothGatt == null) {
                Log.e(TAG, "BLE GATT未连接，无法发送ADPCM数据");
                return;
            }
            
            // 记录发送统计（减少日志频率，每10次记录一次）
            adpcmWriteCounter++;
            if (adpcmWriteCounter % 10 == 0) {
                Log.d(TAG, "TTS ADPCM发送统计: " + adpcmWriteCounter + " 次, 当前数据: " + adpcmData.length + " 字节");
            }
            
            // 注释掉文件保存逻辑，提升性能
            // saveRealtimeAdpcmFile(adpcmData);
            // saveBleSentAdpcmFile(adpcmData);
            
            // 设置特征值
            fff3WriteCharacteristic.setValue(adpcmData);
            
            // 检查特征是否支持Write Without Response
            int props = fff3WriteCharacteristic.getProperties();
            boolean supportsWriteWithoutResponse = (props & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) != 0;
            
            boolean success;
            if (supportsWriteWithoutResponse) {
                // 使用Write Without Response，减少延迟
                fff3WriteCharacteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
                success = bluetoothGatt.writeCharacteristic(fff3WriteCharacteristic);
                // 减少日志输出，只在失败时记录
                if (!success) {
                    Log.e(TAG, "Write Without Response写入FFF3特征失败: " + adpcmData.length + " 字节");
                }
            } else {
                // 降级到普通写入
                fff3WriteCharacteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
                success = bluetoothGatt.writeCharacteristic(fff3WriteCharacteristic);
                // 减少日志输出，只在失败时记录
                if (!success) {
                    Log.e(TAG, "普通Write写入FFF3特征失败: " + adpcmData.length + " 字节");
                }
            }
            
        } catch (Exception e) {
            Log.e(TAG, "写入FFF3特征异常", e);
        }
    }
    
    /**
     * 保存实时编码的ADPCM数据到文件（完全参考DeviceFragment）
     */
    private void saveRealtimeAdpcmFile(byte[] adpcmData) {
        try {
            if (context == null) {
                Log.e(TAG, "Context为空，无法保存文件");
                return;
            }
            
            File externalDir = context.getExternalFilesDir(null);
            if (externalDir == null) {
                Log.e(TAG, "无法获取外部存储目录");
                return;
            }
            
            // 使用追加模式保存实时编码数据
            File realtimeFile = new File(externalDir, "realtime_encoded_adpcm.adpcm");
            FileOutputStream fos = new FileOutputStream(realtimeFile, true);
            fos.write(adpcmData);
            fos.close();
            
            Log.d(TAG, "实时编码ADPCM数据已追加到文件: " + realtimeFile.getAbsolutePath());
            Log.d(TAG, "本次追加数据: " + adpcmData.length + " 字节");
            
        } catch (Exception e) {
            Log.e(TAG, "保存实时编码ADPCM文件失败: " + e.getMessage(), e);
        }
    }
    
    /**
     * 保存实际发送给BLE的ADPCM数据到文件（完全参考DeviceFragment）
     */
    private void saveBleSentAdpcmFile(byte[] adpcmData) {
        try {
            if (context == null) {
                Log.e(TAG, "Context为空，无法保存文件");
                return;
            }
            
            File externalDir = context.getExternalFilesDir(null);
            if (externalDir == null) {
                Log.e(TAG, "无法获取外部存储目录");
                return;
            }
            
            // 使用追加模式保存BLE发送的数据
            File bleSentFile = new File(externalDir, "ble_sent_adpcm.adpcm");
            FileOutputStream fos = new FileOutputStream(bleSentFile, true);
            fos.write(adpcmData);
            fos.close();
            
            Log.d(TAG, "BLE发送ADPCM数据已追加到文件: " + bleSentFile.getAbsolutePath());
            Log.d(TAG, "本次发送数据: " + adpcmData.length + " 字节");
            
        } catch (Exception e) {
            Log.e(TAG, "保存BLE发送ADPCM文件失败: " + e.getMessage(), e);
        }
    }
    
    /**
     * 清空实时编码ADPCM文件（完全参考DeviceFragment）
     */
    private void clearRealtimeAdpcmFile() {
        try {
            if (context == null) {
                Log.e(TAG, "Context为空，无法清空文件");
                return;
            }
            
            File externalDir = context.getExternalFilesDir(null);
            if (externalDir == null) {
                Log.e(TAG, "无法获取外部存储目录");
                return;
            }
            
            File realtimeFile = new File(externalDir, "realtime_encoded_adpcm.adpcm");
            if (realtimeFile.exists()) {
                realtimeFile.delete();
                Log.d(TAG, "已清空实时编码ADPCM文件: " + realtimeFile.getAbsolutePath());
            }
            
        } catch (Exception e) {
            Log.e(TAG, "清空实时编码ADPCM文件失败: " + e.getMessage(), e);
        }
    }
    
    /**
     * 清空BLE发送ADPCM文件（完全参考DeviceFragment）
     */
    private void clearBleSentAdpcmFile() {
        try {
            if (context == null) {
                Log.e(TAG, "Context为空，无法清空文件");
                return;
            }
            
            File externalDir = context.getExternalFilesDir(null);
            if (externalDir == null) {
                Log.e(TAG, "无法获取外部存储目录");
                return;
            }
            
            File bleSentFile = new File(externalDir, "ble_sent_adpcm.adpcm");
            if (bleSentFile.exists()) {
                bleSentFile.delete();
                Log.d(TAG, "已清空BLE发送ADPCM文件: " + bleSentFile.getAbsolutePath());
            }
            
        } catch (Exception e) {
            Log.e(TAG, "清空BLE发送ADPCM文件失败: " + e.getMessage(), e);
        }
    }
    
    /**
     * 字节转16进制字符串（完全参考DeviceFragment）
     */
    private String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02X ", b));
        }
        return sb.toString();
    }
    
    /**
     * 清空ADPCM数据文件（完全参考DeviceFragment）
     */
    private void clearAdpcmDataFile() {
        try {
            if (context == null) {
                Log.e(TAG, "Context为空，无法清空文件");
                return;
            }
            
            File externalDir = context.getExternalFilesDir(null);
            if (externalDir == null) {
                Log.e(TAG, "无法获取外部存储目录");
                return;
            }
            
            // 创建ADPCM数据文件
            File adpcmFile = new File(externalDir, "fff3_adpcm_data.txt");
            
            // 记录清空前的文件大小
            long fileSizeBefore = adpcmFile.length();
            
            // 清空文件内容
            java.io.FileWriter fileWriter = new java.io.FileWriter(adpcmFile, false);
            fileWriter.write(""); // 写入空字符串
            fileWriter.flush(); // 强制刷新
            fileWriter.close();
            
            // 记录清空后的文件大小
            long fileSizeAfter = adpcmFile.length();
            
            Log.d(TAG, "已清空ADPCM数据文件: " + adpcmFile.getAbsolutePath());
            Log.d(TAG, "清空前文件大小: " + fileSizeBefore + " 字节");
            Log.d(TAG, "清空后文件大小: " + fileSizeAfter + " 字节");
            Log.d(TAG, "清空操作成功，文件已重置");
            
        } catch (Exception e) {
            Log.e(TAG, "清空ADPCM数据文件失败: " + e.getMessage(), e);
        }
    }
    
    /**
     * 将ADPCM数据保存到本地txt文件（完全参考DeviceFragment）
     */
    private void saveAdpcmDataToFile(byte[] adpcmData) {
        try {
            if (context == null) {
                Log.e(TAG, "Context为空，无法保存文件");
                return;
            }
            
            // 获取外部存储目录
            File externalDir = context.getExternalFilesDir(null);
            if (externalDir == null) {
                Log.e(TAG, "无法获取外部存储目录");
                return;
            }
            
            // 创建ADPCM数据文件
            File adpcmFile = new File(externalDir, "fff3_adpcm_data.txt");
            
            // 将字节数组转换为十六进制字符串
            String hexString = bytesToHex(adpcmData);
            
            // 记录写入前的文件大小
            long fileSizeBefore = adpcmFile.length();
            
            // 追加写入文件（使用追加模式）
            java.io.FileWriter fileWriter = new java.io.FileWriter(adpcmFile, true);
            java.io.BufferedWriter bufferedWriter = new java.io.BufferedWriter(fileWriter);
            
            // 写入数据
            bufferedWriter.write(hexString);
            bufferedWriter.newLine();
            
            // 强制刷新缓冲区
            bufferedWriter.flush();
            fileWriter.flush();
            
            // 关闭文件
            bufferedWriter.close();
            fileWriter.close();
            
            // 记录写入后的文件大小
            long fileSizeAfter = adpcmFile.length();
            
            // 显示文件路径（只在第一次写入时显示）
            if (fileSizeBefore == 0) { // 第一次写入
                Log.d(TAG, "ADPCM数据已保存到文件: " + adpcmFile.getAbsolutePath());
                Log.d(TAG, "文件路径: " + adpcmFile.getAbsolutePath());
            }
            
            // 记录数据统计信息
            Log.d(TAG, "本次发送数据长度: " + adpcmData.length + " 字节");
            Log.d(TAG, "写入前文件大小: " + fileSizeBefore + " 字节");
            Log.d(TAG, "写入后文件大小: " + fileSizeAfter + " 字节");
            Log.d(TAG, "本次写入增加: " + (fileSizeAfter - fileSizeBefore) + " 字节");
            Log.d(TAG, "保存的十六进制数据: " + hexString);
            
        } catch (Exception e) {
            Log.e(TAG, "保存ADPCM数据到文件失败: " + e.getMessage(), e);
        }
    }
    
    /**
     * 获取最后的TTS PCM数据
     */
    public byte[] getLastTtsPcmData() {
        return lastTtsPcmData;
    }
    
    /**
     * 获取编码后的TTS ADPCM数据
     */
    public byte[] getEncodedTtsAdpcmData() {
        return encodedTtsAdpcmData;
    }
    
    /**
     * 执行TTS编码测试（完全参考DeviceFragment）
     */
    public void performTtsEncodeTest(byte[] pcmData) {
        if (pcmData == null || pcmData.length == 0) return;
        
        try {
            Log.d(TAG, "开始TTS编码测试，PCM长度: " + pcmData.length);
            
            // 将字节数组转换为短整型数组
            short[] pcmShorts = new short[pcmData.length / 2];
            for (int i = 0; i < pcmShorts.length; i++) {
                pcmShorts[i] = (short) ((pcmData[i * 2] & 0xFF) | (pcmData[i * 2 + 1] << 8));
            }
            
            // 编码为ADPCM
            byte[] encodedData = ttsEncoder.encode(pcmShorts);
            
            Log.d(TAG, "TTS编码测试完成，ADPCM长度: " + encodedData.length);
            
            // 保存测试结果
            lastTtsPcmData = pcmData;
            encodedTtsAdpcmData = encodedData;
            
            // 保存测试文件
            saveTestPcmFile(pcmData, "tts_test_input.pcm");
            saveTestAdpcmFile(encodedData, "tts_test_encoded.adpcm");
            saveTestPcmAsWav(pcmData, "tts_test_input.wav");
            
            if (callback != null) {
                callback.onEncodeTestCompleted(encodedData);
            }
            
        } catch (Exception e) {
            Log.e(TAG, "TTS编码测试失败", e);
        }
    }
    
    /**
     * 执行TTS解码测试（完全参考DeviceFragment）
     */
    public void performTtsDecodeTest(byte[] adpcmData) {
        if (adpcmData == null || adpcmData.length == 0) return;
        
        try {
            Log.d(TAG, "开始TTS解码测试，ADPCM长度: " + adpcmData.length);
            
            // 解码ADPCM数据
            short[] pcmShorts = ttsDecoder.decode(adpcmData);
            byte[] decodedData = shortArrayToByteArray(pcmShorts);
            
            Log.d(TAG, "TTS解码测试完成，PCM长度: " + decodedData.length);
            
            // 保存测试文件
            saveTestPcmFile(decodedData, "tts_test_decoded.pcm");
            saveTestPcmAsWav(decodedData, "tts_test_decoded.wav");
            
            // 播放解码后的音频
            // playDecodedAudio(decodedData);
            
            if (callback != null) {
                callback.onDecodeTestCompleted(decodedData);
            }
            
        } catch (Exception e) {
            Log.e(TAG, "TTS解码测试失败", e);
        }
    }
    
    public void setWebSocketUrl(String wsUrl) {
        Log.d(TAG, "设置WebSocket URL: " + wsUrl);
        // 这里可以保存URL，供后续使用
    }
    
    /**
     * 获取ASR提供商配置
     */
    private String getAsrProvider() {
        // 检查缓存是否有效
        long currentTime = System.currentTimeMillis();
        if (cachedAsrProvider != null && (currentTime - lastAsrProviderCheck) < ASR_PROVIDER_CACHE_DURATION) {
            return cachedAsrProvider;
        }
        
        try {
            if (context != null) {
                android.content.SharedPreferences prefs = context.getSharedPreferences("app_config", Context.MODE_PRIVATE);
                String provider = prefs.getString("asr_provider", "doubao");
                
                // 只在值发生变化时打印日志
                if (!provider.equals(cachedAsrProvider)) {
                    Log.d(TAG, "ASR提供商配置更新: " + provider);
                }
                
                // 更新缓存
                cachedAsrProvider = provider;
                lastAsrProviderCheck = currentTime;
                
                return provider;
            } else {
                Log.w(TAG, "context为null，无法获取ASR提供商配置");
            }
        } catch (Exception e) {
            Log.e(TAG, "获取ASR提供商配置失败", e);
        }
        
        // 使用默认值
        cachedAsrProvider = "doubao";
        lastAsrProviderCheck = currentTime;
        return "doubao"; // 默认使用豆包ASR
    }
    
    /**
     * 清除ASR提供商配置缓存
     */
    private void clearAsrProviderCache() {
        cachedAsrProvider = null;
        lastAsrProviderCheck = 0;
        Log.d(TAG, "ASR提供商配置缓存已清除");
    }
    
    /**
     * 检查是否使用豆包ASR
     */
    private boolean isDoubaoAsr() {
        return "doubao".equals(getAsrProvider());
    }
    
    /**
     * 检查是否使用阿里云ASR
     */
    public boolean isAliyunAsr() {
        return "aliyun".equals(getAsrProvider());
    }

    // 处理FFF6按键数据
    public void handleFFF6KeyData(byte[] data) {
        if (data == null || data.length == 0) {
            Log.w(TAG, "FFF6按键数据为空");
            return;
        }
        // 打印完整数据包内容
        StringBuilder sb = new StringBuilder();
        for (byte b : data) {
            sb.append(String.format("%02X ", b));
        }
        Log.d(TAG, "处理FFF6按键数据，内容: " + sb.toString().trim());

        // 假设第一个字节为命令类型，0x01=开悬浮窗，0x00=关悬浮窗
        int cmd = data[3] & 0xFF;
        if (cmd == 0x01) {
            Log.d(TAG, "收到FFF6指令：打开悬浮窗");
            sendFloatWindowControlBroadcast(true);
        } else if (cmd == 0x02) {
            Log.d(TAG, "收到FFF6指令：关闭悬浮窗");
            sendFloatWindowControlBroadcast(false);
        } else {
            Log.w(TAG, "FFF6未知指令: " + cmd);
        }
    }

    // 发送控制悬浮窗的显式广播
    private void sendFloatWindowControlBroadcast(boolean show) {
        Intent intent = new Intent("com.smart.translator.ACTION_FLOAT_WINDOW_CONTROL");
        intent.setComponent(new ComponentName(context.getPackageName(), "com.smart.translator.service.FloatWindowControlReceiver"));
        intent.putExtra("show", show);
        context.sendBroadcast(intent);
        Log.d(TAG, "已发送悬浮窗控制显式广播，show=" + show);
    }

    /**
     * 开始ASR计时
     */
    private void startAsrTiming() {
        if (isAsrTiming) {
            Log.d(TAG, "ASR已在计时中，跳过重复开始");
            return;
        }
        
        asrStartTime = System.currentTimeMillis();
        isAsrTiming = true;
        isAsrStatsUploaded = false;
        Log.d(TAG, "🎯 开始ASR计时");
    }

    /**
     * 停止ASR计时并上传统计数据
     */
    private void stopAsrTimingAndUpload() {
        if (!isAsrTiming) {
            Log.d(TAG, "ASR未在计时中，跳过停止计时");
            return;
        }
        
        long endTime = System.currentTimeMillis();
        long duration = endTime - asrStartTime;
        int seconds = (int) (duration / 1000); // 转换为秒
        
        isAsrTiming = false;
        Log.d(TAG, "⏱️ ASR计时结束，持续时间: " + seconds + "秒");
        
        // 上传统计数据
        uploadAsrStats(seconds);
    }

    /**
     * 上传ASR统计数据
     */
    private void uploadAsrStats(int seconds) {
        if (isAsrStatsUploaded) {
            Log.d(TAG, "ASR统计数据已上传，跳过重复上传");
            return;
        }
        
        if (context == null) {
            Log.w(TAG, "context为null，无法上传ASR统计数据");
            return;
        }
        
        try {
            UserManager userManager = UserManager.getInstance(context);
            if (!userManager.hasValidUserId()) {
                Log.w(TAG, "用户未登录或用户ID无效，跳过上传ASR统计");
                return;
            }

            int userId = userManager.getUserId();
            Log.d(TAG, "准备上传ASR统计数据 - 用户ID: " + userId + ", 时长: " + seconds + "秒");

            // 调用统计API服务
            CompletableFuture<ApiResponse<String>> statsFuture = StatsApiService.uploadAsrStats(context, userId, seconds);
            statsFuture.thenAcceptAsync(response -> {
                if (response.isSuccess()) {
                    Log.d(TAG, "ASR统计数据上传成功: " + response.getData());
                    isAsrStatsUploaded = true;
                } else {
                    Log.e(TAG, "ASR统计数据上传失败: " + response.getError());
                }
            }).exceptionally(throwable -> {
                Log.e(TAG, "ASR统计数据上传异常", throwable);
                return null;
            });

        } catch (Exception e) {
            Log.e(TAG, "上传ASR统计数据失败", e);
        }
    }

    /**
     * 强制停止ASR计时（用于异常情况）
     */
    public void forceStopAsrTiming() {
        if (isAsrTiming) {
            Log.w(TAG, "强制停止ASR计时");
            stopAsrTimingAndUpload();
        }
    }
} 